Emailsherlock
home/API Reference/v1 Base · api.emailsherlock.com
v1 · REST over HTTPS

Email verification, as one JSON request.

Send an 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. One request, one result object.

Every endpoint lives under https://api.emailsherlock.com. Requests are JSON, responses are JSON, authentication is an API key in a header. The example on the right is a complete, copy-paste call. New here? The quickstart walks you from key to first call in five minutes.

Base URL

https://api.emailsherlock.comstringrequired
All paths are relative to this. The API lives on its own host, separate from the website.
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. The score is there to make that call easier.
Request
shell
curl https://api.emailsherlock.com/v1/verify/single \
  -H "X-API-Key: $ES_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]"}'
Response200 OK
application/json
{
    "email": "[email protected]",
    "result": "valid",
    "mx": true,
    "disposable": false,
    "role": false,
    "catch_all": false,
    "score": 0.95,
    "freshness": "fresh"
}
Getting started

Authentication

Authenticate with your API key in the X-API-Key header.

Create a key from your API keys settings and send it on every request. Every key can call both verify endpoints out of the box. Keep the key server-side: a leaked key spends your credits.

X-API-Keyheaderrequired
Your secret API key. A missing or invalid key returns 401 unauthorized.
! Never ship a key to the browser or commit it to git. Read it from an environment variable, as every example here does.
Request
shell
curl https://api.emailsherlock.com/v1/verify/single \
  -H "X-API-Key: $ES_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]"}'
Response401
401 unauthorized
{
  "error": {
    "code": "unauthorized",
    "message": "Invalid API key."
  }
}
    
Core concepts

The verify result

Both endpoints return the same result object, one per address. It carries the verdict and the signals behind it.

emailstringrequired
The address you sent.
resultstringrequired
The verdict for this address. One of valid invalid catch_all disposable role unknown.
mxbooleanrequired
The domain has reachable MX records.
disposablebooleanrequired
Throwaway / temporary-mail provider.
rolebooleanrequired
Role address such as info@ or sales@.
catch_allbooleanrequired
Host accepts mail for any local part.
scorenumber · nullable
0-1 confidence, higher is safer to send to.
freshnessstringrequired
How recent the underlying data is. One of fresh cached_recent cached_stale_refreshed.
Shape
the result object
{
    "email": "[email protected]",
    "result": "valid",
    "mx": true,
    "disposable": false,
    "role": false,
    "catch_all": false,
    "score": 0.95,
    "freshness": "fresh"
}
Endpoints

Verify one email address.

POST /v1/verify/single

The core call. One address in, one result out, typically in under a second.

POST a JSON body with the address. We lowercase and trim it, check syntax, resolve MX, and probe deliverability. Each call costs 1 credit; a verify that the engine can't complete is refunded automatically.

Body parameters

emailstringrequired
The address to verify.

The response is a single result object. The X-Credits-Remaining header reports your balance after the call.

Request
shell
curl https://api.emailsherlock.com/v1/verify/single \
  -H "X-API-Key: $ES_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"[email protected]"}'
Response200 OK
application/json
{
    "email": "[email protected]",
    "result": "valid",
    "mx": true,
    "disposable": false,
    "role": false,
    "catch_all": false,
    "score": 0.95,
    "freshness": "fresh"
}
Endpoints

Verify up to a batch of email addresses in one call.

POST /v1/verify/batch

Up to 100 addresses in one call. Each is verified independently and billed per address.

Send an emails array. You get back a results array in the same order. A bad address in the list does not fail the whole call: that entry carries an error instead of a result, and the rest still run. If your balance runs out mid-batch we stop and the remaining entries report insufficient_credits, so you can see exactly how far we got.

Body parameters

emailsarrayrequired
The addresses to verify. Non-empty, capped per the batch limit.

Per-entry errors

invalid_emailentry error
The entry was not a valid address. It was skipped and not billed.
insufficient_creditsentry error
Your balance ran out at this entry. This and the rest were not verified.
verify_unavailableentry error
The engine could not complete this address. It was refunded; retry it later.
Request
shell
curl https://api.emailsherlock.com/v1/verify/batch \
  -H "X-API-Key: $ES_KEY" \
  -H "Content-Type: application/json" \
  -d '{"emails":["[email protected]","[email protected]"]}'
Response200 OK
application/json
{
    "results": [
        {
            "email": "[email protected]",
            "result": "valid",
            "mx": true,
            "disposable": false,
            "role": false,
            "catch_all": false,
            "score": 0.95,
            "freshness": "fresh"
        },
        {
            "email": "nope@",
            "error": "invalid_email"
        }
    ]
}
Reference

Credits & rate limits

Verifies are paid in credits. A separate per-key rate limit caps how fast you can spend them.

Each verified address costs 1 credit from your account balance, the same wallet the reverse-lookup tool and bulk jobs draw from. The X-Credits-Remaining header on every response tracks what is left. Run out and you get a 402 with X-Credits-Required telling you the shortfall.

Every response also carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (a unix timestamp). Exceed the per-key window and you get a 429 with a Retry-After header. Read it rather than a fixed sleep.

i Need a higher rate or more credits? Pick a plan on the pricing page.
Headers
response headers
HTTP/2 200
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 119
X-RateLimit-Reset: 1751328600
X-Credits-Remaining: 8420
    
Reference

Errors

Conventional HTTP status codes, plus a typed error body you can switch on.

Top-level failures return { "error": { "code", "message" } }. The code is stable and safe to branch on; message is for humans. 2xx is success, 4xx means the request was wrong, and 5xx means we faltered, so retry with backoff.

Status codes

200A result object, or a results array for a batch.
400invalid_requestThe request body was not a JSON object.
401unauthorizedMissing or invalid API key.
402insufficient_creditsNot enough credits for this request.
403forbiddenThe key is not granted the verify:single scope.
422invalid_requestThe "email" field was missing or not a valid address.
429rate_limit_exceededPer-key rate limit exceeded.
503verify_unavailableThe verify engine could not answer; the credit was auto-refunded.
Error shape
application/json
{
  "error": {
    "code": "insufficient_credits",
    "message": "Not enough credits for this request."
  }
}