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.
|
curl https://api.emailsherlock.com/v1/verify/single \
-H "X-API-Key: $ES_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'
import { Emailsherlock } from '@emailsherlock/node';
const es = new Emailsherlock(process.env.ES_KEY);
const result = await es.verify.single({ email: '[email protected]' });
from emailsherlock import Emailsherlock es = Emailsherlock(api_key=os.environ["ES_KEY"]) result = es.verify.single(email="[email protected]")
import emailsherlock "github.com/Emailsherlock1/go"
es := emailsherlock.New(os.Getenv("ES_KEY"))
result, err := es.Verify.Single(ctx, "[email protected]")
<?php
use Emailsherlock\Client;
$es = new Client(getenv('ES_KEY'));
$result = $es->verify->single(['email' => '[email protected]']);
{
"email": "[email protected]",
"result": "valid",
"mx": true,
"disposable": false,
"role": false,
"catch_all": false,
"score": 0.95,
"freshness": "fresh"
}
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.
|
curl https://api.emailsherlock.com/v1/verify/single \
-H "X-API-Key: $ES_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'
import { Emailsherlock } from '@emailsherlock/node';
const es = new Emailsherlock(process.env.ES_KEY);
const result = await es.verify.single({ email: '[email protected]' });
from emailsherlock import Emailsherlock es = Emailsherlock(api_key=os.environ["ES_KEY"]) result = es.verify.single(email="[email protected]")
import emailsherlock "github.com/Emailsherlock1/go"
es := emailsherlock.New(os.Getenv("ES_KEY"))
result, err := es.Verify.Single(ctx, "[email protected]")
<?php
use Emailsherlock\Client;
$es = new Client(getenv('ES_KEY'));
$result = $es->verify->single(['email' => '[email protected]']);
{
"error": {
"code": "unauthorized",
"message": "Invalid API key."
}
}
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.
|
{
"email": "[email protected]",
"result": "valid",
"mx": true,
"disposable": false,
"role": false,
"catch_all": false,
"score": 0.95,
"freshness": "fresh"
}
Verify one email address.
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.
curl https://api.emailsherlock.com/v1/verify/single \
-H "X-API-Key: $ES_KEY" \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]"}'
import { Emailsherlock } from '@emailsherlock/node';
const es = new Emailsherlock(process.env.ES_KEY);
const result = await es.verify.single({ email: '[email protected]' });
from emailsherlock import Emailsherlock es = Emailsherlock(api_key=os.environ["ES_KEY"]) result = es.verify.single(email="[email protected]")
import emailsherlock "github.com/Emailsherlock1/go"
es := emailsherlock.New(os.Getenv("ES_KEY"))
result, err := es.Verify.Single(ctx, "[email protected]")
<?php
use Emailsherlock\Client;
$es = new Client(getenv('ES_KEY'));
$result = $es->verify->single(['email' => '[email protected]']);
{
"email": "[email protected]",
"result": "valid",
"mx": true,
"disposable": false,
"role": false,
"catch_all": false,
"score": 0.95,
"freshness": "fresh"
}
Verify up to a batch of email addresses in one call.
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.
|
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]"]}'
import { Emailsherlock } from '@emailsherlock/node';
const es = new Emailsherlock(process.env.ES_KEY);
const result = await es.verify.batch({ emails: ['[email protected]', '[email protected]'] });
from emailsherlock import Emailsherlock es = Emailsherlock(api_key=os.environ["ES_KEY"]) result = es.verify.batch(emails=["[email protected]", "[email protected]"])
import emailsherlock "github.com/Emailsherlock1/go"
es := emailsherlock.New(os.Getenv("ES_KEY"))
result, err := es.Verify.Batch(ctx, []string{"[email protected]", "[email protected]"})
<?php
use Emailsherlock\Client;
$es = new Client(getenv('ES_KEY'));
$result = $es->verify->batch(['emails' => ['[email protected]', '[email protected]']]);
{
"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"
}
]
}
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.
HTTP/2 200
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 119
X-RateLimit-Reset: 1751328600
X-Credits-Remaining: 8420
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
{
"error": {
"code": "insufficient_credits",
"message": "Not enough credits for this request."
}
}