> Reverse Contact API documentation. This is the Markdown copy of https://docs.reversecontact.com/sdk/python/tasks
> Every page is listed at https://docs.reversecontact.com/llms.txt, every endpoint with its credit cost and status at https://docs.reversecontact.com/catalog.json

# client.tasks

> Retrieve live fetch and contact task states in Python, resume polling with a saved webhook id, and handle task failures, deadlines and results.

- Last verified: 2026-11-04

Read or wait for a live fetch or contact task by its saved webhook id.

From SDK 0.4.0, `client.tasks`, `Task`, `AsyncTask`, `TaskFailedError` and `TaskTimeoutError` replace `client.jobs`, `Job`, `AsyncJob`, `JobFailedError` and `JobTimeoutError`. The former names remain as deprecated aliases of the same objects, so existing `except` and `isinstance` checks keep working, and the errors also expose `job_id` with the value of `task_id`.

| Method | Endpoint | Cost |
| ------ | -------- | ---- |
| [`retrieve()`](#retrieve) | [GET /v2/webhooks/{webhookId}](https://docs.reversecontact.com/guides/polling) | Free (0 credits), and does not count toward your per-minute rate limit. |
| [`wait()`](#wait) | [GET /v2/webhooks/{webhookId}](https://docs.reversecontact.com/guides/polling) | Free (0 credits), and does not count toward your per-minute rate limit. |

## Calling conventions

Examples assume `RC_API_KEY` is set. Replace example ids with ids returned by your own requests. Signatures show the published 0.4.0 synchronous methods. Use the same arguments with the [Python async client](https://docs.reversecontact.com/sdk/python/async-client).

`models` refers to `reversecontact.types`. `NOT_GIVEN` and `NotGiven` are the SDK's internal markers for omitted arguments. Leave these arguments out of your calls. For API body parameters, passing `None` sends an explicit null. Transport options use `None` to inherit their defaults. `Timeout` means a number of seconds or `httpx.Timeout`. Supply parameters marked **Required** to Python or to the API, even when the generated signature permits omission.

JSON response objects expose `data`, `quotas`, `metadata` and `http_response`. Check optional fields for `None`. See [First call](https://docs.reversecontact.com/sdk/python/first-call) for the response envelope. CSV methods return text and iterators yield items.

HTTP failures raise an `APIError` subclass based on the response: `BadRequestError`, `AuthenticationError`, `InsufficientCreditsError`, `PermissionDeniedError`, `NotFoundError`, `ConflictError`, `GoneError`, `UnprocessableEntityError`, `RateLimitError`, `DailyLimitError`, `KeyCreditLimitError`, `UnavailableForLegalReasonsError` or `InternalServerError`. See the [error mapping and retry rules](https://docs.reversecontact.com/sdk/python/errors-and-retries).

For Bulk task ids, use [client.bulk](https://docs.reversecontact.com/sdk/python/bulk). For List operation ids, use [client.lists](https://docs.reversecontact.com/sdk/python/lists).

## retrieve

Read the current task state with `client.tasks.retrieve()`. See [Polling](https://docs.reversecontact.com/guides/polling) for details.

**Python SDK**

```python [Python SDK]
def retrieve(
    webhook_id: str,
    *,
    wait: int | NotGiven | None = NOT_GIVEN,
    timeout: Timeout | None = None,
    max_retries: int | None = None,
    headers: Mapping[str, str] | None = None,
    **extra: object,
) -> Result[models.PollWebhookData]: ...
```

**Parameters**

| Name | Type | Description |
| ---- | ---- | ----------- |
| `webhook_id` | `str` | **Required.** Saved webhookId from a live fetch or contact task. |
| `wait` | `int \| NotGiven \| None` | Optional. Seconds the API may hold the request while the task runs, from `0` to `20`. Absent or `0`: the API answers at once, as a normal poll. Any other value returns `422` with `VALIDATION_ERROR`. |
| `timeout` | `Timeout \| None` | Optional. Seconds per HTTP attempt, or `httpx.Timeout`. Uses the client setting when `None`. |
| `max_retries` | `int \| None` | Optional. Retries after the first HTTP attempt. Uses the client setting when `None`. |
| `headers` | `Mapping[str, str] \| None` | Optional. Additional HTTP headers for this call. |
| `**extra` | `object` | Optional. Additional API keyword arguments, including camelCase aliases, passed through to the API. |

**Returns**

`Result[models.PollWebhookData]`. `data` is one task snapshot, including `status`, `error_code`, `result`, `delivery_status` and `credits_consumed`. `result` is decoded JSON. An `errored` task is returned without raising `TaskFailedError`.

**Errors**

`APIError` subclasses follow the HTTP mapping above. `APIConnectionError` reports transport failures. `APITimeoutError` reports timed-out attempts. `ReverseContactError` covers invalid SDK options or a `wait` outside the integer range 0 to 20. Malformed typed response data can raise Pydantic `ValidationError`.

**Example**

**Python SDK**

```python [Python SDK]
from reversecontact import ReverseContact

with ReverseContact() as client:
    result = client.tasks.retrieve("00000000-0000-4000-8000-000000000001", wait=20)
    print(result.data if result is not None else None)
```
## wait

Wait for the task to finish with `client.tasks.wait()`. See [Polling](https://docs.reversecontact.com/guides/polling) for details.

**Python SDK**

```python [Python SDK]
def wait(
    task_id: str,
    *,
    timeout: float = 1800,
    poll_wait: int = 20,
    on_poll: Callable[[Result[TaskSnapshot[object]]], None] | None = None,
    headers: Mapping[str, str] | None = None,
) -> Result[TaskSnapshot[object]]: ...
```

**Parameters**

| Name | Type | Description |
| ---- | ---- | ----------- |
| `task_id` | `str` | **Required.** Saved `webhookId` from a live fetch or contact task, also available as `task.id`. |
| `timeout` | `float` | Optional. Overall polling deadline in seconds. Default `1800`. |
| `poll_wait` | `int` | Optional. Long-poll duration from `0` to `20` seconds. Default `20`. |
| `on_poll` | `Callable[[Result[TaskSnapshot[object]]], None] \| None` | Optional. Synchronous callback called with each successful poll response. |
| `headers` | `Mapping[str, str] \| None` | Optional. Additional HTTP headers for this call. |

**Returns**

`Result[TaskSnapshot[object]]`. `data` is the successful task snapshot. `data.result` is decoded JSON and does not use the original task handle's typed result parser. No new enrichment task is created.

**Errors**

`APIError` subclasses follow the HTTP mapping above. `APIConnectionError` reports transport failures. `APITimeoutError` reports timed-out attempts. `ReverseContactError` covers invalid `poll_wait` or `timeout`. `wait()` raises `TaskFailedError` for an errored task and `TaskTimeoutError` when its overall deadline expires. Malformed typed response data can raise Pydantic `ValidationError`.

**Example**

**Python SDK**

```python [Python SDK]
from reversecontact import ReverseContact

with ReverseContact() as client:
    result = client.tasks.wait("00000000-0000-4000-8000-000000000001")
    print(result.data if result is not None else None)
```
## Related guides

See the [Python SDK overview](https://docs.reversecontact.com/sdk/python), [Async tasks](https://docs.reversecontact.com/sdk/python/async-tasks), [Fetch](https://docs.reversecontact.com/sdk/python/fetch) and [Contact](https://docs.reversecontact.com/sdk/python/contact).

## FAQ

### Which task id does client.tasks accept?

`client.tasks` accepts the `webhookId` returned by live fetch and contact endpoints, also exposed as `task.id`. Bulk tasks use `client.bulk`.

### Does tasks.retrieve raise TaskFailedError?

`client.tasks.retrieve()` returns an `errored` state as data. `client.tasks.wait()` raises `TaskFailedError` for that state.

### Does resuming tasks.wait create another paid task?

`client.tasks.wait(task_id)` polls the existing task for free. Resuming does not create or bill another enrichment task.
