Quickstart
POST /v1/verifications asks about an address, and
GET /v1/verifications/{id} retrieves an answer that was not ready in time. That
is the whole of an integration at a signup form, and this page is about it.
Beside it: GET /v1/domain/{domain} reports how a
domain receives mail and what it publishes about sending it, for one credit
(two with the domain’s registration date); and
three free lookups each answer one narrow question about a domain -
throwaway provider, catch-all and
public mailbox provider. Everything else on this site
explains what comes back.
curl -sS https://api.emvero.tech/v1/verifications \ -H "Authorization: Bearer emv_your_credential" \ -H "Content-Type: application/json" \ -H "Idempotency-Key: signup-8f21c0" \ -d '{"email":"ada@example.com"}'Make the credential at emvero.io/account/api-keys/ - it is shown once, so copy it before leaving the page. Authentication has the rest.
email is the only required field. variant chooses how deep
to check and defaults to the most complete depth - omit it unless you have read
that page and want the cheaper one.
{ "id": "5f0b6f3e-1a4c-4a1f-9d2e-8f7b3c2a1d90", "email": "ada@example.com", "normalized": { "domain": "example.com", "ascii_domain": "example.com" }, "status": "deliverable", "confidence": 0.92, "action": "allow", "checks": { "syntax": "valid", "domain": "valid", "mail_routing": "valid", "smtp": "accepted", "accept_all": "no", "disposable": false, "role_account": false, "public_provider": false, "smtp_utf8_required": false }, "reason_codes": ["MX_FOUND", "SMTP_RCPT_ACCEPTED"], "freshness": { "dns_checked_at": "2026-09-05T09:14:22Z", "smtp_checked_at": "2026-09-05T09:14:23Z" }}Three fields carry the answer, and they are deliberately separate:
status- what the evidence says. One ofdeliverable,undeliverable,risky,unknown,pending.action- what we recommend doing about it in a registration flow:allow,allow_with_email_confirmationorreject. Your product may weigh the same evidence differently; nothing aboutactionis binding.reason_codes- why, from a closed vocabulary that is added to but never repurposed. Branch on these rather than on prose.
confidence is a rule-based score and not a probability.
checks reports each question’s outcome separately, so you can see which one
failed rather than only the verdict.
Handle the two cases that are not a verdict
Section titled “Handle the two cases that are not a verdict”status: "pending" means recipient evidence is still being gathered. The
response carries retry_after_ms; wait that long and GET /v1/verifications/{id}. There are no callbacks. See
Pending results.
A negative verdict is a 200. An address that fails verification is a
successful request. The 4xx and 5xx responses mean the request was malformed or
the service could not answer - never that the address is unusable. See
Errors.
A minimal integration
Section titled “A minimal integration”async function verify(email, idempotencyKey) { const post = await fetch('https://api.emvero.tech/v1/verifications', { method: 'POST', headers: { Authorization: `Bearer ${process.env.EMVERO_TOKEN}`, 'Content-Type': 'application/json', 'Idempotency-Key': idempotencyKey, }, body: JSON.stringify({ email }), });
if (!post.ok) throw new Error(`emvero: ${post.status}`);
let result = await post.json();
// Poll only while the answer is genuinely outstanding, and honour the hint: // it is how long the service expects the outstanding work to take. while (result.status === 'pending') { await new Promise((r) => setTimeout(r, result.retry_after_ms ?? 2000)); const get = await fetch( `https://api.emvero.tech/v1/verifications/${result.id}`, { headers: { Authorization: `Bearer ${process.env.EMVERO_TOKEN}` } }, ); if (!get.ok) throw new Error(`emvero: ${get.status}`); result = await get.json(); }
return result;}Two things this deliberately does not do. It does not treat a thrown error as a
bad address - if the service cannot answer, the registration should proceed
behind a confirmation message, not fail. And it does not poll forever; give the
loop a deadline of your own and treat expiry as unknown.
Then read
Section titled “Then read”Verdicts and pending before you write the branch that decides what to do with one.