Email Finder
Find a verified email address for a contact at a domain
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: found→email + verificationare present; a deliverable or risky mailbox was found at this domain.status: not_found→emailandverificationare explicitnull; 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 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 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.
1 <= length <= 200The 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.
1 <= length <= 253Response 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 }}{ "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" }}{ "statusCode": 429, "error": "Too Many Requests", "message": "upstream email verification is temporarily throttled", "retryAfter": 30}Submit a bulk 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_countis 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: errorwith anerror_code.
Authorization
ApiKeyAuth 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.
1 <= items <= 1000Response 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}Poll a bulk find-email batch
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.found—email+verificationpresent (same shape as the single endpoint).not_found— resolved definitively with no verified mailbox;emailandverificationare explicitnull.error— terminal failure for this row;error_codeis one ofinvalid_input(name/domain unparseable),upstream_failed(verifier failure on this domain), orincomplete(the batch finished but this row's domain group exhausted its retries).
Batches are retained for 30 days after creation.
Authorization
ApiKeyAuth API key authentication using Bearer token. Format: sk_live_ followed by a secure random string.
In: header
Path Parameters
The batch_id returned by the submit call.
uuidResponse 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 } ]}