Reference

API documentation

A REST API for finding a person’s work email from their name and company domain, and verifying it against the receiving mail server before you send. Every response is JSON. The base URL is https://www.findleademails.com.

Authentication

Create a key under Settings. It is shown once and stored only as a SHA-256 hash, so it cannot be recovered later — generate a new one if you lose it. Pass it on every request:

curl https://www.findleademails.com/api/v1/email/find \
  -H "x-api-key: fle_live_..." \
  -H "content-type: application/json" \
  -d '{"first_name":"Sarah","last_name":"Jones","company_domain":"example.com"}'

A Bearer token is accepted in place of the header. Requests without a valid key return 401.

Find one email

POST /api/v1/email/find

{
  "email": "sarah.jones@example.com",
  "status": "verified",
  "verification_status": "valid",
  "confidence": 0.99,
  "confidence_label": "VERY_HIGH",
  "needs_verification": false,
  "credits_used": 1,
  "credits_remaining": 942
}

status is one of verified (the mail server accepted the mailbox — safe to send), catch_all (the domain accepts every address, so nothing can be confirmed and a prediction is returned), predicted (no verdict available), or not_found (every candidate was rejected).

Stable fields are email, status, confidence, needs_verification, credits_used and credits_remaining. Other fields may be added over time.

Find in bulk

POST /api/v1/bulk/find takes a records array and answers in the same request. It is meant for interactive use and is capped per request; oversized batches return 413 with code: "batch_too_large" and the limit in max_rows.

Rows are grouped by domain, so a company’s convention is resolved once and reused for everyone at it. For anything larger, use jobs.

Jobs (async)

POST /api/v1/jobs accepts up to 50,000 records, returns immediately with 202, and runs off-request.

curl https://www.findleademails.com/api/v1/jobs \
  -H "x-api-key: fle_live_..." \
  -H "content-type: application/json" \
  -H "Idempotency-Key: your-unique-id" \
  -d '{"records":[{"first_name":"Sarah","last_name":"Jones","company_domain":"example.com"}],
       "callback_url":"https://your-app.example/hooks"}'

Send an Idempotency-Key so a retry returns the original job instead of creating and charging a second one.

Poll GET /api/v1/jobs/{id} for counters, and page results with GET /api/v1/jobs/{id}/results?cursor=0 until next_cursor comes back null. Results are readable while the job is still running. DELETE /api/v1/jobs/{id} cancels one.

If you set callback_url, completion POSTs a job.completed payload signed as x-fle-signature: sha256=<hmac> over the raw body. Verify it before trusting the payload. Delivery is attempted once and a failure never fails the job, so treat polling as the reliable path.

What you are charged

You are billed only for a result you can use. A verified or catch_all result costs 1 credit. not_found is free, and so is a repeat lookup of someone already found. A predicted result is free whenever verification ran but could not reach a verdict.

Credits never expire, and they survive downgrade and cancellation.

Errors

Errors carry an HTTP status and, where it helps, a stable machine-readable code.

401  Unauthorized            missing or revoked API key
402  insufficient_credits    top up, or choose a larger plan
413  batch_too_large         split the batch; see max_rows
413  job_too_large           more than 50,000 records in one job
429  too_many_queued_jobs    let a running job finish first
503  jobs_unavailable        async jobs are not configured

A 5xx is safe to retry. For job creation, retry with the same Idempotency-Key so you are never charged twice.

Need a higher volume rate?

If you are embedding this in a product or reselling enrichment, the per-credit rate drops well below the published plans.

hello@vestalhub.com