Less boo. More booked. Halloween offer: 30 days free on any paid plan. Claim 30 days freeEvery new account gets one free mailbox for warmup and replies. No domain to buy. See how it works

Skip to content

Email Finder

API reference6 min read8 sections

Find and verify a person's or company's email address from a domain, website, or business name, optionally narrowed to a specific person. Lookups run asynchronously as jobs: most resolve in a few seconds, but cache misses can take longer while Warmerly scrapes and verifies candidates, so the API returns immediately with either a completed result or a job you poll.

All Email Finder endpoints require X-Api-Key. Endpoints that create or read job data are project-scoped and also require X-Project-Id (missing or malformed: 400 bad_request; a project you are not a member of: 403 forbidden; an unknown project: 404 not_found); GET /email-finder/quota is account-level and does not require X-Project-Id.

API reference

#Single lookup

text
POST /email-finder/lookup

Submit one lookup. Provide at least one of domain, website, or name, add person to narrow the search to a specific individual at that domain/company.

FieldTypeDescription
domainstringCompany domain, e.g. "acme.com".
websitestringFull website URL; the domain is extracted from it.
namestringBusiness name, used when no domain or website is given. If domain is also sent, domain is used.
locationstringOptional location hint to disambiguate a business name.
person.firstNamestringOptional first name to target a specific person.
person.lastNamestringOptional last name to target a specific person.

person is used with a business name lookup. If none of domain, website or name gives a usable value the request returns 400 bad_request (provide a valid domain, website, or business name). If you are out of lookup quota it returns 402 quota_exhausted (see Quota).

bash
curl https://app.warmerly.com/api/v1/email-finder/lookup \
  -X POST \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" \
  -H "Content-Type: application/json" \
  -d '{
    "domain": "acme.com",
    "person": { "firstName": "Jane", "lastName": "Doe" }
  }'

If the answer for that domain is already cached, the lookup completes synchronously and returns 200 with the result inline (result is null if the cache holds no email for the domain):

json
{
  "status": "done",
  "jobId": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10",
  "job": {
    "id": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10",
    "status": "done",
    "confidence": 92,
    "error": null,
    "createdAt": "2026-07-02T09:14:03.000Z",
    "completedAt": "2026-07-02T09:14:03.000Z"
  },
  "result": {
    "email": "jane.doe@acme.com",
    "confidence": 92,
    "verifyStatus": "verified",
    "source": "pattern_guess",
    "isCatchAll": false,
    "mxHost": "aspmx.l.google.com",
    "evidenceUrl": "https://acme.com/team",
    "providerName": "Google Workspace"
  }
}

Otherwise it enqueues a job and returns 202 with a pollUrl:

json
{
  "status": "pending",
  "jobId": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10",
  "pollUrl": "https://app.warmerly.com/api/v1/email-finder/jobs/3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10"
}

Poll the job (see below) until status is "done" or "failed".

API reference

#Bulk lookup

text
POST /email-finder/bulk

Submit up to 1,000 lookups in one request. Each item accepts the same fields as a single lookup. All items are enqueued under a shared batchId you can use to track progress via Batches.

bash
curl https://app.warmerly.com/api/v1/email-finder/bulk \
  -X POST \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a" \
  -H "Content-Type: application/json" \
  -d '{
    "items": [
      { "domain": "acme.com", "person": { "firstName": "Jane", "lastName": "Doe" } },
      { "website": "https://widgetco.io" },
      { "name": "Roasted Coffee Co", "location": "Austin, TX" }
    ]
  }'
json
{
  "batchId": "6e6f9d0a-4a3f-4c7e-9c86-1b6a4e5c2f01",
  "results": [
    { "index": 0, "ok": true, "jobId": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10", "cached": true, "result": { "email": "jane.doe@acme.com", "confidence": 92, "verifyStatus": "verified", "source": "pattern_guess", "isCatchAll": false, "mxHost": "aspmx.l.google.com", "evidenceUrl": "https://acme.com/team", "providerName": "Google Workspace" } },
    { "index": 1, "ok": true, "jobId": "7c1e9b3d-8a2f-4e11-9d0c-5b3a1f4e6c22", "cached": false },
    { "index": 2, "ok": false, "error": "invalid input" }
  ]
}

items must hold 1 to 1,000 entries, otherwise 400 bad_request (invalid_body). Each item is evaluated independently: an invalid item (ok: false) does not fail the rest of the batch. Items that hit the cache resolve immediately (cached: true, result present); the rest are enqueued (cached: false) and must be polled individually via their jobId, or tracked in aggregate via batch status.

API reference

#Get a job

text
GET /email-finder/jobs/:id

Fetch the current status of a lookup job, whether it came from a single or bulk request.

bash
curl https://app.warmerly.com/api/v1/email-finder/jobs/3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10 \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a"
json
{
  "job": {
    "id": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10",
    "status": "scraping",
    "confidence": null,
    "error": null,
    "createdAt": "2026-07-02T09:14:03.000Z",
    "completedAt": null
  },
  "result": null
}

status moves through pending → resolving → scraping → verifying → done (or failed). result is populated once status is "done" (and is null if no email was found); on "failed", check job.error for the reason. A job that doesn't exist, or that belongs to a different project than the one in X-Project-Id, returns 404 not_found.

API reference

#Delete a job

text
DELETE /email-finder/jobs/:id

Deletes the job and its discovered email records.

bash
curl https://app.warmerly.com/api/v1/email-finder/jobs/3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10 \
  -X DELETE \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a"
json
{ "deleted": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10" }
API reference

#Batch status

text
GET /email-finder/batches/:id

Returns aggregate progress for a bulk lookup, grouped by job status, for the project in X-Project-Id. A batch id that matches no jobs in that project returns total: 0 rather than a 404.

bash
curl https://app.warmerly.com/api/v1/email-finder/batches/6e6f9d0a-4a3f-4c7e-9c86-1b6a4e5c2f01 \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a"
json
{
  "batchId": "6e6f9d0a-4a3f-4c7e-9c86-1b6a4e5c2f01",
  "total": 3,
  "done": 2,
  "pending": 1,
  "counts": {
    "done": 2,
    "scraping": 1
  }
}

done sums jobs in either done or failed status. Use List results with batchId to fetch the actual emails once a batch is complete.

API reference

#List results

text
GET /email-finder/results

Lists jobs for the current project, each joined with its winning discovered email (if any), newest first. Cursor-paginated.

Query paramTypeDescription
statusstringFilter by job status: pending, resolving, scraping, verifying, done, failed.
batchIduuidRestrict to jobs from a specific bulk batch.
minConfidenceinteger (0-100)Only include results with confidence at or above this value.
cursorISO 8601 datetimePass the previous response's nextCursor to fetch the next page.
limitinteger (1-100, default 25)Page size.
bash
curl "https://app.warmerly.com/api/v1/email-finder/results?status=done&limit=25" \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
  -H "X-Project-Id: 8f14e45f-ceea-4c6a-8c8d-6b1a5b5c9c1a"
json
{
  "results": [
    {
      "id": "3f9a2e2a-1c4b-4a2e-9b1e-2f6c8a7d5e10",
      "status": "done",
      "confidence": 92,
      "inputDomain": "acme.com",
      "inputName": null,
      "batchId": null,
      "createdAt": "2026-07-02T09:14:03.000Z",
      "email": "jane.doe@acme.com",
      "verifyStatus": "verified",
      "source": "pattern_guess"
    }
  ],
  "nextCursor": "2026-07-02T09:14:03.000Z"
}

Pass nextCursor as the cursor query param to fetch the next page; it is null on the last page.

API reference

#Quota

text
GET /email-finder/quota

Returns your current monthly Email Finder usage. This endpoint is account-level, it does not require X-Project-Id.

bash
curl https://app.warmerly.com/api/v1/email-finder/quota \
  -H "X-Api-Key: wmv_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
json
{ "used": 37, "limit": 500, "remaining": 463 }

The limit depends on your plan; with no active plan the allowance is 50 lookups a month. Both POST /email-finder/lookup and POST /email-finder/bulk check remaining quota before enqueuing. A bulk request counts against quota by item count, plus any of your earlier lookups that are still queued. If the request would exceed your limit, it's rejected with 402 quota_exhausted:

json
{
  "error": {
    "code": "quota_exhausted",
    "message": "You've used 500 of 500 email lookups this month. Upgrade your plan to continue.",
    "details": {
      "label": "email lookups",
      "used": 500,
      "limit": 500,
      "topUpUrl": null,
      "upgradeUrl": "/settings/billing"
    }
  }
}

The message text varies: when credits can cover the shortfall it offers them, and details.topUp and details.topUpUrl are set.

API reference

#Errors

StatusCodeWhen
400bad_requestMissing or malformed X-Project-Id (project-scoped endpoints), invalid body/query, or no valid domain/website/name provided.
401unauthorizedMissing, invalid, or revoked API key.
402quota_exhaustedMonthly lookup quota used up (lookup and bulk).
403forbiddenYou are not a member of the project in X-Project-Id.
403agency_plan_requiredAPI keys only work while the workspace the request acts on is on the Agency plan.
404not_foundProject, or job, doesn't exist or doesn't belong to the given project.
429too_many_requestsThe API key's per-minute rate limit was exceeded.
Was this page helpful?