Skip to content

MaintenanceThe former company search endpoint goes into maintenance on November 9Migration guide

SDKs // Python // Guides

Async tasks

Last verified

Wait for live profiles, Find Email, Verify Email and Find Phone tasks in Python, resume polling by id, or parse webhook deliveries from the API.

fetch.person_live, fetch.company_live, contact.find_email, contact.verify_email and contact.find_phone start a task and return a task handle right away. task.id is the task's webhookId.

Call task.wait() to poll the task until it ends. When the task succeeds, the method returns its final state in data (status, result, credits_consumed). When the task fails, the method raises TaskFailedError. Polling is free and does not count toward your rate limit.

Python SDK

Live fetch

import os

from reversecontact import TaskFailedError, TaskTimeoutError, ReverseContact

with ReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
    task = client.fetch.person_live(url="https://social.com/in/janedoe")
    # Save the id first: after a restart, client.tasks.wait(id) resumes without paying for a new task.
    print("Task id:", task.id)

    try:
        done = task.wait(timeout=1800)
        if done.data is not None and done.data.result is not None:
            print(done.data.result.first_name, "credits:", done.data.credits_consumed)
    except TaskFailedError as error:
        print("Task failed:", error.error_code, "credits:", error.credits_consumed)
    except TaskTimeoutError as error:
        print("Still running, resume later with client.tasks.wait:", error.task_id)

How wait() behaves:

  • Each poll asks the API to hold the answer for up to 20 seconds (poll_wait, 0 to 20), so the result arrives as soon as the task ends. Two polls start at least Retry-After seconds apart, 2 seconds when the header is missing.
  • timeout is the overall deadline in seconds, 1800 (30 minutes) by default. When the deadline passes, wait() raises TaskTimeoutError with task_id and last_status. The task may still finish. Resume polling with client.tasks.wait(task_id). The synchronous client can exceed the deadline by the length of the poll in progress.
  • A task that ends with status errored raises TaskFailedError, with error_code, credits_consumed, result and not_found. The not_found field is True for data-not-found, person-not-found, company-not-found, email-not-found and phone-not-found.
  • The SDK calls on_poll with each state it reads.
  • The SDK never starts a new task after a failure. Your code decides whether to start another task, since the new task can be billed again.

client.tasks.retrieve(task_id, wait=20) reads one state of a task without waiting for the end. Polling describes the task lifecycle and how long a result stays available.

Webhook delivery instead of polling

Pass webhook_url when you create the task. The API sends the result to that HTTPS URL as {webhookId, data}.

Use parse_webhook_delivery to parse the decoded body, a JSON string or bytes. The helper checks the delivery's shape and returns webhook_id, data and is_error. The is_error field is True when data.errorCode is a non-empty string. A malformed delivery raises ReverseContactError. The helper does not validate the profile itself.

Python SDK

Webhook delivery

import os

from reversecontact import ReverseContact, parse_webhook_delivery

with ReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
    task = client.fetch.person_live(
        url="https://social.com/in/janedoe",
        webhook_url="https://your-app.com/webhooks/reversecontact",
    )
    print("Store this id to match the delivery:", task.id)


# Call this from the route behind webhook_url with the raw request body.
def handle_webhook(body: bytes) -> None:
    delivery = parse_webhook_delivery(body)
    if delivery.is_error:
        print(delivery.webhook_id, "failed:", delivery.data)
    else:
        print(delivery.webhook_id, "result:", delivery.data)
    # Answer within 10 seconds, then process the data: deduplicate on webhook_id.

You can still poll a task created with webhook_url by calling task.wait(). See Webhooks for delivery failures and retries.

Read one state from a task handle

task.retrieve(wait=20) returns one typed Result[TaskSnapshot[T]]. The profile or contact result keeps the type of the method that created the task. Unlike wait(), retrieve() returns an errored state without raising TaskFailedError.

Python SDK

Python SDK

from reversecontact import ReverseContact

with ReverseContact() as client:
    task = client.contact.find_phone(url="https://social.com/in/janedoe")
    state = task.retrieve(wait=20)
    if state.data:
        print(state.data.status, state.data.result)

After a restart, use client.tasks to retrieve a task or wait for the result by id. client.tasks.wait(task_id) returns the endpoint-specific result as decoded JSON. The original Task handle parses that result into its typed model.

client.fetch and client.contact list the task-creating methods. Bulk tasks and List operations use their own helpers, described in Lists and Bulk enrichment.

Return to the Python SDK overview.

FAQ

How do I wait for a live fetch or Find Email result in Python?

Save task.id and call task.wait(). Polling is free and waits up to 1800 seconds by default. Resume after a restart with client.tasks.wait(task_id).

What happens when a Python SDK task fails?

task.wait() raises TaskFailedError for an errored task. The exception includes task_id, error_code, credits_consumed, result and not_found.

Does TaskTimeoutError cancel the enrichment task?

TaskTimeoutError ends local waiting, without cancelling the remote task. Resume polling with the exception's task_id.

Can I use webhooks and polling together in Python?

Pass webhook_url to a live fetch or contact method and parse deliveries with parse_webhook_delivery. The same task remains available through task.wait().