---
title: "Email Verification API for Developers | Emvero"
description: "Verify addresses through one REST endpoint. Read status, action and reason codes in JSON; poll pending checks. Start with credits on a confirmed account."
url: https://emvero.io/email-verification-api/
language: en
updated: 2026-10-07
---

Email verification API

# Verify email addresses through a REST API

Send an email address from your server to check its format, domain and mail routing. A full check can also gather evidence about the mailbox from the receiving mail server. The JSON response includes a status, a recommended action and the reasons for the result.

No email is sent during verification. When the check cannot determine whether the address can receive mail, Emvero returns an unknown result.

Start for free

View documentation

Server-side REST API · JSON results · Polling for pending checks

## Make a request from your server

Create a bearer credential in your account and keep it on your server. Send it in the `Authorization` header with each request. The JSON body requires an `email` value.

The request below uses `full`, the default verification depth. It checks syntax, the domain and mail routing, and can probe the receiving server for mailbox evidence. To stop before the SMTP probe, include `"variant":"domain"` in the request body. Both depths use the same endpoint and response fields. A domain check cannot establish whether an individual mailbox exists.

```
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"}'
```

Reuse the same `Idempotency-Key` when retrying this request. Within the API’s replay window, this prevents a retry or duplicate submission from starting another verification.

The following HTTP `200` response is illustrative. Its address, identifier and evidence are fictional; they do not describe a live check of `example.com`:

```
{
  "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"]
}
```

HTTP `200` means the request succeeded, including when the address is `undeliverable`. Read the JSON result to find out what the check established about the address. HTTP errors describe a problem with the request or service.

## Read the fields together

`status` describes the result. The four final values are `deliverable`, `risky`, `undeliverable` and `unknown`. `pending` means the check is still running.

| Status | Meaning | Recommended action |
| --- | --- | --- |
| deliverable | The server accepted the recipient and no risk signals were found | `allow` |
| risky | A specific risk signal affects how the address should be handled | `allow_with_email_confirmation` / `allow` |
| undeliverable | The check found a permanent technical reason to reject the address | `reject` |
| unknown | The available evidence could not determine whether the address can receive mail | `allow_with_email_confirmation` |
| pending | The check is still running | Retrieve the result after `retry_after_ms` |

`action` recommends how to handle the address: accept it with `allow`, use a confirmation step with `allow_with_email_confirmation`, or turn it away with `reject`. Your application decides how to apply the recommendation. Read the returned field rather than inferring it from `status`: a `risky` result can carry either `allow` or `allow_with_email_confirmation`, depending on the evidence.

To understand the result, inspect `checks` for each stage’s outcome and any risk signals. `reason_codes` explains the findings with stable identifiers such as `DISPOSABLE_DOMAIN` or `SMTP_RCPT_ACCEPTED`. The [single-address verification guide](https://emvero.io/email-verification/) explains what syntax, routing and SMTP checks can establish.

`confidence` is an evidence score from 0 to 1. The example’s `0.92` is not a 92% probability of inbox delivery. A verification result also does not establish that a person controls the mailbox; use a separate email confirmation when that matters.

## Poll when a full check is still running

A full check can return `pending` while it gathers mailbox evidence. The response includes the evidence collected so far, an `id` and `retry_after_ms`, the interval to wait before retrieving the result. This illustrative response shows only the fields needed for polling:

```
{
  "id": "5f0b6f3e-1a4c-4a1f-9d2e-8f7b3c2a1d90",
  "status": "pending",
  "retry_after_ms": 2000
}
```

Wait for `retry_after_ms` milliseconds, then call `GET /v1/verifications/{id}` with the same bearer credential. Replace `{id}` with the identifier from the response. If the result is still `pending`, wait for the returned interval before polling again. Stop polling when you receive a final status or reach your application’s deadline. The API does not send a callback. The [pending results documentation](https://docs.emvero.io/using/pending/) covers this process in detail.

Reaching your deadline does not mean the address is invalid. A completed check can also return `unknown` if a timeout or server restriction leaves too little evidence for a definite result. Keep unfinished work separate from a final `unknown` result in your application.

## Handle request errors separately

An HTTP error does not tell you whether the address can receive mail. Handle it according to the response code:

- `400`: correct the request.
- `401`: check the bearer credential.
- `402`: the account has insufficient credits.
- `429`: reduce the request rate and honour `Retry-After` when supplied.
- `5xx`: the service could not return a verification result. Do not treat this as an address rejection.

If you retry the same operation, preserve its idempotency key. The [quickstart](https://docs.emvero.io/start/quickstart/) shows a basic integration, and the [error reference](https://docs.emvero.io/using/errors/) explains the response codes.

For a form where someone is waiting, the [real-time verification page](https://emvero.io/real-time-email-verification/) explains how to set a wait deadline and handle the result. For an existing list, the [bulk verification page](https://emvero.io/bulk-email-verification/) explains how to run one request per address and store the results in your own system. There is no hosted CSV upload or separate batch endpoint.

Questions

## Frequently asked.

**What does an email verification API return?**

The JSON response includes an `id`, a `status` describing the result and an `action` recommending how to handle the address. `checks` records the individual check results, `reason_codes` explains the findings with stable identifiers, and `confidence` scores the evidence. A check that is still running returns `pending` so you can retrieve the result later.

**Is this an email validation API as well?**

Yes. The API validates the address format, then checks the domain and its mail routing. A full check can also use SMTP to gather evidence about the mailbox. You can choose a domain check to stop before that SMTP probe, but it cannot establish whether the individual mailbox exists.

**Does the API send a verification message?**

No. An SMTP probe stops before `DATA`, the stage where message content would be sent. No subject or body is submitted. If you need to confirm that someone controls the mailbox, your application must send a separate confirmation email.

**Can the API prove every mailbox exists?**

No. A catch-all server may accept any recipient name, so acceptance alone cannot prove that a particular mailbox exists. Timeouts and server restrictions can also leave the check without enough evidence. These limits may lead to `risky` or `unknown`. Even a `deliverable` result does not guarantee future delivery or show who controls the mailbox.

**Can I try the email verification API for free?**

Yes. Create an account and confirm your email address to receive 1,000 credits without a card. They cover 100 full checks or up to 500 domain checks. Create a bearer credential in your account to use those credits through the API.

## Compared side by side

### A score, or the evidence behind it

An evidence score summarises the result. Individual checks and reason codes explain what was found and where uncertainty remains.

### Catch-all domain

A domain that accepts arbitrary recipient names, so an accepted address may have no individual mailbox.

Send your first request

## Try the API with your account credits

Create an account and confirm your email address to receive 1,000 credits. No card is required. Use them for 100 full checks or up to 500 domain checks.

Start for free

View pricing
