Emailsherlock
home/API/Quickstart/v1 Base · api.emailsherlock.com
Quickstart · v1

Your first check in five minutes.

Send one address. Get back whether it is deliverable, whether the domain has working mail, whether it is a disposable or role address, and a confidence score. Here is the whole path, from key to production, in five steps.

An emailsherlock account A terminal & curl or an SDK About 5 minutes
01Step

Get an API key

Sign in and create a key in your API keys settings. The key is shown once and cannot be recovered, so copy it straight away. There are two key types: a sandbox key (prefix es_test_) returns deterministic fixtures and spends nothing, so you can build against it first; a live key (prefix es_live_) verifies real addresses. The free tier gives you 100 live verifies a month. See sandbox testing for the test addresses.

Export it as an environment variable so it never touches your code. Every example below reads ES_KEY from the environment and sends it in the X-API-Key header.

Export your key
shell · ~/.zshrc
export ES_KEY="4f8c92a17b3d…"
! Never ship a key to the browser or commit it to git. A leaked key spends your credits. Keep it server-side and rotate it from the settings page if it is exposed.
02Step

Install the SDK

Pick your language. Each SDK is a thin wrapper over one HTTPS endpoint, all open source. If you would rather not add a dependency, curl works everywhere and needs nothing.

shell · npm
# node 18+ · ESM or CommonJS
npm install @emailsherlock/node
03Step

Run your first check

One address in, one result out, typically in under a second. The call on the right is complete and copy-paste ready. Swap the address for one of your own.

The body is a single field, email. The response is one result object with the verdict and every signal behind it. The same shape comes back from the batch endpoint, one per address.

Request
shell
curl https://api.emailsherlock.com/v1/credits \
  -H "X-API-Key: $ES_KEY" \
  -H "Content-Type: application/json" \
  -d '[]'
Response200 OK
application/json
{
    "plan": "Free",
    "sandbox": false
}
04Step

Read the result

The result field is the verdict. The booleans and the score are the signals behind it, so you can branch on whichever matters to your flow.

emailstring
The address you sent.
resultstring
The verdict for this address. One of valid invalid catch_all disposable role unknown.
deliverableboolean · nullable
Proven deliverability: true only after the mailbox accepted RCPT TO, false only when the address provably fails (bad syntax, no MX, hard reject). Null means unproven, not bad: disposable, role and catch_all short-circuit before the SMTP probe.
reasonstring · nullable
Why the pipeline decided. greylisted, smtp_timeout, smtp_unreachable and verification_pending are transient: retry the address later. Null on results cached before reasons existed. One of bad_syntax no_mx mailbox_accepts mailbox_not_found disposable_provider role_address catch_all_domain accept_all_provider greylisted smtp_timeout smtp_unreachable verification_pending blocked_domain spam_trap .
mxboolean
The domain has reachable MX records.
mx_recordstring · nullable
The primary MX host, when one was resolved during this check.
disposableboolean
Throwaway / temporary-mail provider.
roleboolean
Role address such as info@ or sales@.
catch_allboolean
Host accepts mail for any local part.
free_emailboolean · nullable
The domain is a freemail provider (gmail.com, web.de, ...). Null when the domain is not classified yet.
relayboolean
The address sits on a relay / forwarding / alias-masking service (SimpleLogin, Apple Hide My Email, Cloudflare Email Routing, ...). The address is deliverable and reaches a real person, it is just masked, so this never changes the verdict or decision. Use it to apply your own policy on masked senders.
relay_providerstring · nullable
Name of the relay provider when relay is true, null otherwise.
parkedboolean
The address is on a parked or for-sale domain. Informational only: it never changes the verdict, but a parked domain rarely runs a real mailbox.
spam_trapboolean
The mail host is a known or suspected spam trap. Informational only: it never changes the verdict, and it is never a hard block. But sending to a trap hurts your sender reputation, so the recommendation drops to review. See spam_trap_type for how it was identified.
spam_trap_typestring · nullable
How the trap was identified: known_trap_domain (the mail host is on our curated trap registry) or reputation_heuristic (it matched a conservative parked + spam-list heuristic). Null when spam_trap is false. One of known_trap_domain reputation_heuristic .
suggested_correctionstring · nullable
A corrected address when the domain looks like a typo of a high-volume domain (gmial.com -> [email protected]). Null when nothing looks mistyped. Advisory only: it never changes the verdict, so show it as a "did you mean" hint and let the sender decide.
smtp_diagnosisstring · nullable
Enhanced scan only: the granular mailbox state read from the SMTP reply (mailbox_full, mailbox_disabled, mailbox_not_found, greylist_deferred, policy_block, accepted). Null on Quick / Standard scans, which do not run the deep probe. Explains the verdict, never overrides it. One of accepted mailbox_full mailbox_disabled mailbox_not_found greylist_deferred policy_block .
scorenumber · nullable
0-1 confidence, higher is safer to send to.
freshnessstring
How recent the underlying data is. One of fresh cached_recent cached_stale_refreshed.
checked_atstring · nullable
When the underlying verification ran (ISO 8601). On cached results this is the original check, not the request time.
domainobject · nullable
Domain-level intelligence. Null when the domain has not been crawled yet.
decisionobject
degradedboolean
Email-Guard only: true when your monthly remote-decision quota is used up and the Verify API declined to run a remote check. The SDK falls back to its local checks (syntax + the bundled disposable list) until the quota resets at the start of next month. false on every normal response. See docs/decisions/email-guard.md.
i Results are facts, not opinions. A role or catch_all address is not "bad". Whether it is safe enough to send to stays your call. Branch on result (stable enum) and score, and the X-Credits-Remaining header tells you what is left.
05Step

Move to production

Your first call already hit the live API, so there is no key or endpoint to swap. Four things separate a demo from a production integration.

Scrub lists with /v1/verify/jobs/{id}
Send up to 100 addresses in one call instead of looping single checks. Same result object, one per address.
Watch your credits
On any paid plan, verify is free up to 10,000 verifies a month: read X-Verify-Free-Remaining to see what is left. Past that, or without a subscription, each verify costs 0 credits, tracked by X-Credits-Remaining. Run out and you get a 402. A verify the engine can't complete is auto-refunded.
Back off on 429
Read the Retry-After header and wait that many seconds rather than a fixed sleep. Every response also carries X-RateLimit-Reset.
Keep the key server-side
Read it from an environment variable, as every example here does. A missing or invalid key returns 401.
Keep going

Where to next.

Reference Full API reference Every endpoint, parameter and result field, with live request and response samples in five languages. Endpoints Verify a whole batch Run up to 100 addresses through one call and scrub a list before you send to it. Plans Pricing & credits What each plan allows per minute and per month, and how credits are billed and roll over. Overview What the API does Validity, disposable and role detection, catch-all, MX and a confidence score, in one JSON object.
That's the whole API

One key. One request.