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

# Timeouts and cancellation

> Configure HTTP timeouts, set an overall deadline for Python job polling, and cancel asyncio waits without starting duplicate enrichment requests.

- Last verified: 2026-11-04

Each HTTP attempt times out after 90 seconds by default, since some enrichments take more than 60 seconds. Every API method accepts the keyword arguments `timeout` (seconds per attempt, or an `httpx.Timeout`), `max_retries` and `headers`.

With `AsyncReverseContact`, use `asyncio.timeout()` or cancel the call's asyncio task. The synchronous client has no cancel handle. Limit each call with `timeout`, and each job wait with `job.wait(timeout=...)`. Cancellation stops your code from waiting but does not cancel a job on the server.

**Timeout and cancellation**

```python [Python SDK]
import asyncio
import os

from reversecontact import AsyncReverseContact

async def main() -> None:
    async with AsyncReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
        async with asyncio.timeout(30):
            usage = await client.usage.retrieve(timeout=10.0, max_retries=1)
        if usage.quotas and usage.quotas.workspace and usage.quotas.workspace.credits:
            print("Credits left:", usage.quotas.workspace.credits.left)

asyncio.run(main())
```

## HTTP attempts and polling deadlines

On an API request, `timeout` limits each HTTP attempt through httpx's timeout settings. Retries can extend the total elapsed time. For polling requests, finite HTTP timeout components increase to at least `wait + 15` seconds. A `wait()` helper then caps those components at the time remaining before its overall deadline.

On `job.wait()`, `client.jobs.wait()`, `client.bulk.wait()` and `client.lists.operations.wait()`, `timeout` is an overall deadline. The default is 1800 seconds. The helpers accept `poll_wait` from 0 to 20 and raise `ReverseContactError` for invalid polling values or a non-finite, negative timeout. A synchronous wait can overrun by one bounded HTTP phase. An async wait uses an asyncio deadline.

The wait helpers handle polling failures separately from per-request `max_retries`. They retry eligible consecutive API or connection failures up to four times, within the deadline. A successful poll resets the retry count.

## Stop server-side bulk work

Local asyncio cancellation does not cancel server-side work. For Bulk jobs, call [client.bulk.cancel()](https://docs.reversecontact.com/sdk/python/bulk#cancel). For a List operation, call [client.lists.operations.cancel()](https://docs.reversecontact.com/sdk/python/lists#operationscancel). These are explicit API operations with their own return values.

See [Async jobs](https://docs.reversecontact.com/sdk/python/async-jobs) to resume a timed-out enrichment and [Errors and retries](https://docs.reversecontact.com/sdk/python/errors-and-retries) for transport error handling.

Return to the [Python SDK overview](https://docs.reversecontact.com/sdk/python).

## FAQ

### What is the default Python SDK request timeout?

The SDK configures a 90-second timeout per HTTP attempt. Pass `timeout` to the client or API method to change the httpx timeout settings.

### How is job.wait timeout different from a request timeout?

`job.wait(timeout=1800)` sets an overall polling deadline. A request timeout applies to each HTTP attempt. Retries can extend the total elapsed time.

### Does cancelling an asyncio task cancel a Reverse Contact job?

Asyncio cancellation stops local waiting. Use `bulk.cancel()` or `lists.operations.cancel()` for explicit server-side Bulk or List cancellation.

### Can a synchronous job wait exceed its deadline?

A synchronous wait can exceed its deadline by one bounded HTTP phase. `JobTimeoutError` retains the job id and last status for resuming later.
