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

> Find email addresses and phone numbers or verify an email with the Python SDK, then wait for typed job results with safe idempotent retries.

- Last verified: 2026-11-04

Find email addresses and phone numbers or verify an email. Each method returns a job handle.

| Method | Endpoint | Cost |
| ------ | -------- | ---- |
| [`find_email()`](#find_email) | [POST /v2/contact/email](https://docs.reversecontact.com/endpoints/contact-email) | 3 credits when a professional email is found, 5 for a personal one, regardless of emailType. An any lookup costs 3, 5 or 8 (8 when it finds both). A lookup that finds none is free. |
| [`verify_email()`](#verify_email) | [POST /v2/contact/email/verify](https://docs.reversecontact.com/endpoints/contact-email-verify) | 1 credit per verdict, whatever it says. A check that fails is refunded. |
| [`find_phone()`](#find_phone) | [POST /v2/contact/phone](https://docs.reversecontact.com/endpoints/contact-phone) | 20 credits when a phone number is found. A lookup that finds none is free. |

## 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).

All three methods generate an `Idempotency-Key` when omitted and reuse that key on automatic retries. See [Safe retries](https://docs.reversecontact.com/sdk/python/errors-and-retries#safe-retries-on-find-email-and-find-phone).

## find_email

Supply `url`, `id`, `full_name` with `company_domain`, or `first_name` and `last_name` with `company_domain`. The API defaults `email_type` to `professional`.

**Python SDK**

```python [Python SDK]
def find_email(
    *,
    url: str | NotGiven | None = NOT_GIVEN,
    id: str | NotGiven | None = NOT_GIVEN,
    full_name: str | NotGiven | None = NOT_GIVEN,
    first_name: str | NotGiven | None = NOT_GIVEN,
    last_name: str | NotGiven | None = NOT_GIVEN,
    company_domain: str | NotGiven | None = NOT_GIVEN,
    email_type: str | NotGiven | None = NOT_GIVEN,
    webhook_url: str | NotGiven | None = NOT_GIVEN,
    timeout: Timeout | None = None,
    max_retries: int | None = None,
    headers: Mapping[str, str] | None = None,
    idempotency_key: str | None = None,
    **extra: object,
) -> Job[list[ContactValue | None]]: ...
```

**Parameters**

| Name | Type | Description |
| ---- | ---- | ----------- |
| `url` | `str \| NotGiven \| None` | **Required for the selected strategy.** Public Social profile URL, such as `https://www.social.com/in/janedoe`. Use this for the URL strategy. |
| `id` | `str \| NotGiven \| None` | **Required for the selected strategy.** Reverse Contact person id from a previous response, such as `prs_01jbd5vewyenebxgaz869ffe5t`. Use this for the id strategy. |
| `full_name` | `str \| NotGiven \| None` | **Required for the selected strategy.** Person's full name, such as `Jane Doe`. Use this with `company_domain`. |
| `first_name` | `str \| NotGiven \| None` | **Required for the selected strategy.** Person's first name. Use this with `last_name` and `company_domain` instead of `full_name`. |
| `last_name` | `str \| NotGiven \| None` | **Required for the selected strategy.** Person's last name. Use this with `first_name` and `company_domain` instead of `full_name`. |
| `company_domain` | `str \| NotGiven \| None` | **Required for the selected strategy.** Company domain, such as `acme.com`. Required for the name-based strategies. |
| `email_type` | `str \| NotGiven \| None` | Optional. Kind of email to find: `professional` (default), `personal`, or `any` to accept either. Omit it to find professional emails. |
| `webhook_url` | `str \| NotGiven \| None` | Optional. HTTPS URL that receives the callback. Omit it to retrieve the result by polling instead. |
| `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. |
| `idempotency_key` | `str \| None` | Optional. Request-specific key, 1 to 255 printable ASCII characters without spaces. The SDK generates a key when omitted and reuses it on retries. |
| `**extra` | `object` | Optional. Additional API keyword arguments, including camelCase aliases, passed through to the API. |

**Returns**

`Job[list[ContactValue | None]]`. A job acknowledgement with `id`, `data`, `quotas`, `metadata`, `http_response` and `replayed`. Save `job.id` before waiting. Call `job.wait()` to get `Result[JobSnapshot[T]]` with the final value in `data.result`. The final value is a list of `ContactValue` models with `value` and `type`. Entries can be `None`. See [Async jobs](https://docs.reversecontact.com/sdk/python/async-jobs) for details.

**Errors**

`APIError` subclasses follow the HTTP mapping above. `APIConnectionError` reports transport failures. `APITimeoutError` reports timed-out attempts. `ReverseContactError` covers invalid SDK options or a missing job id in the acknowledgement. Invalid `idempotency_key` values raise `ReverseContactError` before the request. `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:
    job = client.contact.find_email(url="https://social.com/in/janedoe")
    print("Save this job id:", job.id)
    done = job.wait()
    print(done.data.result if done.data else None)
```
## verify_email

Provide the required `email` to start a verification job. Call `wait()` to get the verdict.

**Python SDK**

```python [Python SDK]
def verify_email(
    *,
    email: str | NotGiven | None = NOT_GIVEN,
    webhook_url: str | NotGiven | None = NOT_GIVEN,
    timeout: Timeout | None = None,
    max_retries: int | None = None,
    headers: Mapping[str, str] | None = None,
    idempotency_key: str | None = None,
    **extra: object,
) -> Job[models.ContactEmailVerifyResult]: ...
```

**Parameters**

| Name | Type | Description |
| ---- | ---- | ----------- |
| `email` | `str \| NotGiven \| None` | **Required.** The email address to check, such as `jane@acme.com`. |
| `webhook_url` | `str \| NotGiven \| None` | Optional. HTTPS URL that receives the result, including error outcomes. Omit it to poll for the verdict instead. |
| `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. |
| `idempotency_key` | `str \| None` | Optional. Request-specific key, 1 to 255 printable ASCII characters without spaces. The SDK generates a key when omitted and reuses it on retries. |
| `**extra` | `object` | Optional. Additional API keyword arguments, including camelCase aliases, passed through to the API. |

**Returns**

`Job[models.ContactEmailVerifyResult]`. A job acknowledgement with `id`, `data`, `quotas`, `metadata`, `http_response` and `replayed`. Save `job.id` before waiting. Call `job.wait()` to get `Result[JobSnapshot[T]]` with the final value in `data.result`. The final value contains `email` and `status`. See [Async jobs](https://docs.reversecontact.com/sdk/python/async-jobs) for details.

**Errors**

`APIError` subclasses follow the HTTP mapping above. `APIConnectionError` reports transport failures. `APITimeoutError` reports timed-out attempts. `ReverseContactError` covers invalid SDK options or a missing job id in the acknowledgement. Invalid `idempotency_key` values raise `ReverseContactError` before the request. `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:
    job = client.contact.verify_email(email="jane@acme.com")
    print("Save this job id:", job.id)
    done = job.wait()
    print(done.data.result if done.data else None)
```
## find_phone

Supply `url`, `id`, `full_name` with `company_domain`, or `first_name` and `last_name` with `company_domain`.

**Python SDK**

```python [Python SDK]
def find_phone(
    *,
    url: str | NotGiven | None = NOT_GIVEN,
    id: str | NotGiven | None = NOT_GIVEN,
    full_name: str | NotGiven | None = NOT_GIVEN,
    first_name: str | NotGiven | None = NOT_GIVEN,
    last_name: str | NotGiven | None = NOT_GIVEN,
    company_domain: str | NotGiven | None = NOT_GIVEN,
    webhook_url: str | NotGiven | None = NOT_GIVEN,
    timeout: Timeout | None = None,
    max_retries: int | None = None,
    headers: Mapping[str, str] | None = None,
    idempotency_key: str | None = None,
    **extra: object,
) -> Job[list[ContactValue | None]]: ...
```

**Parameters**

| Name | Type | Description |
| ---- | ---- | ----------- |
| `url` | `str \| NotGiven \| None` | **Required for the selected strategy.** Public Social profile URL, such as `https://www.social.com/in/janedoe`. Use this for the URL strategy. |
| `id` | `str \| NotGiven \| None` | **Required for the selected strategy.** Reverse Contact person id from a previous response, such as `prs_01jbd5vewyenebxgaz869ffe5t`. Use this for the id strategy. |
| `full_name` | `str \| NotGiven \| None` | **Required for the selected strategy.** Person's full name, such as `Jane Doe`. Use this with `company_domain`. |
| `first_name` | `str \| NotGiven \| None` | **Required for the selected strategy.** Person's first name. Use this with `last_name` and `company_domain` instead of `full_name`. |
| `last_name` | `str \| NotGiven \| None` | **Required for the selected strategy.** Person's last name. Use this with `first_name` and `company_domain` instead of `full_name`. |
| `company_domain` | `str \| NotGiven \| None` | **Required for the selected strategy.** Company domain, such as `acme.com`. Required for the name-based strategies. |
| `webhook_url` | `str \| NotGiven \| None` | Optional. HTTPS URL that receives the callback. Omit it to retrieve the result by polling instead. |
| `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. |
| `idempotency_key` | `str \| None` | Optional. Request-specific key, 1 to 255 printable ASCII characters without spaces. The SDK generates a key when omitted and reuses it on retries. |
| `**extra` | `object` | Optional. Additional API keyword arguments, including camelCase aliases, passed through to the API. |

**Returns**

`Job[list[ContactValue | None]]`. A job acknowledgement with `id`, `data`, `quotas`, `metadata`, `http_response` and `replayed`. Save `job.id` before waiting. Call `job.wait()` to get `Result[JobSnapshot[T]]` with the final value in `data.result`. The final value is a list of `ContactValue` models with `value` and `type`. Entries can be `None`. See [Async jobs](https://docs.reversecontact.com/sdk/python/async-jobs) for details.

**Errors**

`APIError` subclasses follow the HTTP mapping above. `APIConnectionError` reports transport failures. `APITimeoutError` reports timed-out attempts. `ReverseContactError` covers invalid SDK options or a missing job id in the acknowledgement. Invalid `idempotency_key` values raise `ReverseContactError` before the request. `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:
    job = client.contact.find_phone(url="https://social.com/in/janedoe")
    print("Save this job id:", job.id)
    done = job.wait()
    print(done.data.result if done.data 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) and [Errors and retries](https://docs.reversecontact.com/sdk/python/errors-and-retries).

## FAQ

### Does find_email return an email immediately?

`client.contact.find_email()` returns a `Job`. Call `job.wait()` and read `done.data.result` for the list of contact values.

### What does verify_email return in Python?

`client.contact.verify_email()` returns a job whose final result has `email` and `status`. Read that result after `job.wait()`.

### How do I avoid duplicate contact jobs on retry?

Contact methods generate an idempotency key for each call and reuse that key on automatic retries. Supply a stored `idempotency_key` to safely retry the same body after a restart.
