SDKs // Python // Guides
Async jobs
Last verified
Wait for live profiles, Find Email, Verify Email and Find Phone jobs 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 job and return a job handle right away. job.id is the job's webhookId.
Call job.wait() to poll the job until it ends. When the job succeeds, the method returns its final state in data (status, result, credits_consumed). When the job fails, the method raises JobFailedError. Polling is free and does not count toward your rate limit.
Live fetch
import os
from reversecontact import JobFailedError, JobTimeoutError, ReverseContact
with ReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
job = client.fetch.person_live(url="https://social.com/in/janedoe")
# Save the id first: after a restart, client.jobs.wait(id) resumes without paying for a new job.
print("Job id:", job.id)
try:
done = job.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 JobFailedError as error:
print("Job failed:", error.error_code, "credits:", error.credits_consumed)
except JobTimeoutError as error:
print("Still running, resume later with client.jobs.wait:", error.job_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 job ends. Two polls start at leastRetry-Afterseconds apart, 2 seconds when the header is missing. timeoutis the overall deadline in seconds, 1800 (30 minutes) by default. When the deadline passes,wait()raisesJobTimeoutErrorwithjob_idandlast_status. The job may still finish. Resume polling withclient.jobs.wait(job_id). The synchronous client can exceed the deadline by the length of the poll in progress.- A job that ends with
statuserroredraisesJobFailedError, witherror_code,credits_consumed,resultandnot_found. Thenot_foundfield isTruefordata-not-found,person-not-found,company-not-found,email-not-foundandphone-not-found. - The SDK calls
on_pollwith each state it reads. - The SDK never starts a new job after a failure. Your code decides whether to start another job, since the new job can be billed again.
client.jobs.retrieve(job_id, wait=20) reads one state of a job without waiting for the end. Polling describes the job lifecycle and how long a result stays available.
Webhook delivery instead of polling
Pass webhook_url when you create the job. 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.
Webhook delivery
import os
from reversecontact import ReverseContact, parse_webhook_delivery
with ReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
job = 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:", job.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 job created with webhook_url by calling job.wait(). See Webhooks for delivery failures and retries.
Read one state from a job handle
job.retrieve(wait=20) returns one typed Result[JobSnapshot[T]]. The profile or contact result keeps the type of the method that created the job. Unlike wait(), retrieve() returns an errored state without raising JobFailedError.
Python SDK
from reversecontact import ReverseContact
with ReverseContact() as client:
job = client.contact.find_phone(url="https://social.com/in/janedoe")
state = job.retrieve(wait=20)
if state.data:
print(state.data.status, state.data.result)After a restart, use client.jobs to retrieve a job or wait for the result by id. client.jobs.wait(job_id) returns the endpoint-specific result as decoded JSON. The original Job handle parses that result into its typed model.
client.fetch and client.contact list the job-creating methods. Bulk jobs 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 job.id and call job.wait(). Polling is free and waits up to 1800 seconds by default. Resume after a restart with client.jobs.wait(job_id).
What happens when a Python SDK job fails?
job.wait() raises JobFailedError for an errored job. The exception includes job_id, error_code, credits_consumed, result and not_found.
Does JobTimeoutError cancel the enrichment job?
JobTimeoutError ends local waiting, without cancelling the remote job. Resume polling with the exception's job_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 job remains available through job.wait().