> Reverse Contact API documentation. This is the Markdown copy of https://docs.reversecontact.com/sdk/python/jobs
> 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.jobs

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

- Last verified: 2026-11-04

Read or wait for a live fetch or contact job by its saved webhook 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.3.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 job 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 job state with `client.jobs.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 job. |
| `wait` | `int \| NotGiven \| None` | Optional. Seconds the API may hold the request while the job 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 job snapshot, including `status`, `error_code`, `result`, `delivery_status` and `credits_consumed`. `result` is decoded JSON. An `errored` job is returned without raising `JobFailedError`.

**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.jobs.retrieve("00000000-0000-4000-8000-000000000001", wait=20)
    print(result.data if result is not None else None)
```
## wait

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

**Python SDK**

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

**Parameters**

| Name | Type | Description |
| ---- | ---- | ----------- |
| `job_id` | `str` | **Required.** Saved `webhookId` from a live fetch or contact job, also available as `job.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[JobSnapshot[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[JobSnapshot[object]]`. `data` is the successful job snapshot. `data.result` is decoded JSON and does not use the original job handle's typed result parser. No new enrichment job 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 `JobFailedError` for an errored job and `JobTimeoutError` 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.jobs.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 jobs](https://docs.reversecontact.com/sdk/python/async-jobs), [Fetch](https://docs.reversecontact.com/sdk/python/fetch) and [Contact](https://docs.reversecontact.com/sdk/python/contact).

## FAQ

### Which job id does client.jobs accept?

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

### Does jobs.retrieve raise JobFailedError?

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

### Does resuming jobs.wait create another paid job?

`client.jobs.wait(job_id)` polls the existing job for free. Resuming does not create or bill another enrichment job.
