Email Finder

Find a verified email address for a contact at a domain

POST
/v1/contacts/find-email

Given a contact's full name and the domain of the company they work for, returns a verified email address along with verification metadata.

Under the hood, the service maintains a learning pattern store: it tries patterns previously verified for the domain first (the "warm path"), then falls back to a parallel sweep of all common templates against the Emailable verifier (the "cold path") if no cached pattern verifies. Patterns are global — every customer's verification feeds every other customer's first lookup at that domain.

Names with European tussenvoegsels (Joey van Ommen, Joey van der Ommen) are handled — the service tries both "tussenvoegsel-included" and "tussenvoegsel-excluded" surname renderings.

Response semantics

Always branch on the status field first — do not null-check verification directly.

  • status: foundemail + verification are present; a deliverable or risky mailbox was found at this domain.
  • status: not_foundemail and verification are explicit null; we tried the full candidate set within a 15-second budget and no mailbox verified as deliverable. Distinct from a server error.
  • verification.accept_all = true → the domain is configured as catch-all, so the verifier cannot distinguish real mailboxes from accepted-but-discarded ones. The returned email is our best guess (modal real-world pattern) but should be treated as lower confidence.

Credits

Each call charges 0.1 credits on success — both when a deliverable email is found and when no email is found (the verification attempt itself consumed work). Requests rejected before any verification work begins (validation errors, upstream outages, pre-filter short-circuits like invalid domain syntax) are not charged. Requests rejected due to insufficient credit balance return 402 before any verification work is performed.

Authorization

ApiKeyAuth
AuthorizationBearer <token>

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

full_name*string

Full name of the contact. Accepts 2-3 token names (Joey Ommen, Joey Tobias Ommen) and 3-4 token names where the middle tokens form a recognized European name particle (Joey van Ommen, Joey van der Ommen). Single-token names and names longer than 4 tokens are rejected with 422.

Length1 <= length <= 200
domain*string

The mail domain for the contact's company. Accepts bare domains (saber.app), domains with www. prefix, and trailing-dot forms. URL-shaped inputs (https://saber.app) and email-shaped inputs (joey@saber.app) are rejected with 422.

Length1 <= length <= 253

Response Body

application/json

application/json

application/json

curl -X POST "https://example.com/v1/contacts/find-email" \  -H "Content-Type: application/json" \  -d '{    "full_name": "Joey Ommen",    "domain": "saber.app"  }'

{  "status": "found",  "email": "joey.vanommen@saber.app",  "verification": {    "state": "deliverable",    "score": 95,    "accept_all": false  }}

Empty
Empty
{  "error": {    "type": "PAYMENT_REQUIRED",    "code": "PAYMENT_REQUIRED",    "errorCode": "INSUFFICIENT_CREDITS",    "message": "Organization has insufficient credits",    "details": {      "remainingCredits": 0.05    },    "requestId": "550e8400-e29b-41d4-a716-446655440000"  }}
Empty
{  "statusCode": 429,  "error": "Too Many Requests",  "message": "upstream email verification is temporarily throttled",  "retryAfter": 30}
Empty

Submit a bulk find-email batch

POST
/v1/contacts/find-email/batch

Accepts up to 1,000 (full_name, domain) pairs and resolves them asynchronously through the same engine as the single find-email endpoint. Returns 202 with a batch_id immediately; poll GET /v1/contacts/find-email/batch/{id} for progress and per-contact results.

Server-side behaviors that replace client-side loops:

  • Pacing + retries against the upstream verifier — no client-side 429 handling needed; throttle waves are absorbed with backoff inside the batch.
  • Domain grouping — contacts at the same domain are resolved together, so the first resolution warms the pattern store and the rest reuse it.
  • Domain normalization + duplicate collapsing — domains are normalized (lowercased, www. and trailing dots stripped) before grouping, and case-insensitive duplicate (full_name, domain) pairs are collapsed; row_count is the deduplicated count. Poll results echo the normalized domain.
  • Partial results, always — an upstream failure affecting one domain never discards other rows' results; affected rows end in status: error with an error_code.

Authorization

ApiKeyAuth
AuthorizationBearer <token>

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

In: header

Request Body

application/json

TypeScript Definitions

Use the request body type in TypeScript.

contacts*array<>
Items1 <= items <= 1000

Response Body

application/json

curl -X POST "https://example.com/v1/contacts/find-email/batch" \  -H "Content-Type: application/json" \  -d '{    "contacts": [      {        "full_name": "Aadil Merchant",        "domain": "collectiveartists.com"      },      {        "full_name": "Kathy Kaplan",        "domain": "collectiveartists.com"      }    ]  }'
{  "batch_id": "4da22c97-b7d5-4e31-8c3a-03870ebc7b20",  "status": "pending",  "row_count": 0}
Empty
Empty
Empty
Empty

Poll a bulk find-email batch

GET
/v1/contacts/find-email/batch/{id}

Returns the batch status, progress counters, and every contact's current outcome. Rows resolve incrementally — poll until status is completed (or, rarely, failed). Per-contact status values:

  • pending — not resolved yet.
  • foundemail + verification present (same shape as the single endpoint).
  • not_found — resolved definitively with no verified mailbox; email and verification are explicit null.
  • error — terminal failure for this row; error_code is one of invalid_input (name/domain unparseable), upstream_failed (verifier failure on this domain), or incomplete (the batch finished but this row's domain group exhausted its retries).

Batches are retained for 30 days after creation.

Authorization

ApiKeyAuth
AuthorizationBearer <token>

API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.

In: header

Path Parameters

id*string

The batch_id returned by the submit call.

Formatuuid

Response Body

application/json

curl -X GET "https://example.com/v1/contacts/find-email/batch/497f6eca-6276-4993-bfeb-53cbbbba6f08"
{  "batch_id": "6f1a1c9e-9df9-4a4f-9df0-2f8f6f7a4b31",  "status": "running",  "progress": {    "total": 3,    "pending": 1,    "found": 1,    "not_found": 1,    "error": 0  },  "contacts": [    {      "full_name": "Aadil Merchant",      "domain": "collectiveartists.com",      "status": "found",      "email": "aadil.merchant@collectiveartists.com",      "verification": {        "state": "deliverable",        "score": 93,        "accept_all": false      }    },    {      "full_name": "Manjula K.L",      "domain": "capstonelife.in",      "status": "not_found",      "email": null,      "verification": null    },    {      "full_name": "Kathy Kaplan",      "domain": "relevatehealth.com",      "status": "pending",      "email": null,      "verification": null    }  ]}
Empty
Empty
Empty

On this page