# Email verification API

URL: https://email-validation.org/email-verification-api/
Updated: 2026-10-20

> Documentation index: https://email-validation.org/llms.txt

A REST API that tells you whether an email address can receive mail: a status, a reason and a recommended action for
every address, in real time or for whole lists. Results with the status `unknown` never cost a credit, and new
accounts start with 500 free credits.

<p class="cluster"><a class="btn btn-primary btn-lg" href="/signin/">Get an API key</a> <a class="btn btn-lg" href="/docs/quickstart/">Read the quickstart</a></p>

## Your first request

**curl**

```bash
curl https://api.email-validation.org/v1/validate \
  -H "Authorization: Bearer $EV_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "accepted@sandbox.email-validation.org"}'
```

**JavaScript**

```js
// Node.js 18+, Deno, Bun or Cloudflare Workers: fetch is built in.
const res = await fetch('https://api.email-validation.org/v1/validate', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.EV_API_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ email: 'accepted@sandbox.email-validation.org' }),
});
const body = await res.json();
if (!res.ok) throw new Error(`${body.error.code}: ${body.error.message}`);
console.log(body.status, body.reason, body.action);
```

**Python**

```python
import os

import requests

resp = requests.post(
    "https://api.email-validation.org/v1/validate",
    headers={"Authorization": f"Bearer {os.environ['EV_API_KEY']}"},
    json={"email": "accepted@sandbox.email-validation.org"},
    timeout=20,
)
body = resp.json()
if not resp.ok:
    raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
print(body["status"], body["reason"], body["action"])
```

The answer looks like this:

```json
{
  "email": "accepted@sandbox.email-validation.org",
  "status": "deliverable",
  "reason": "accepted",
  "action": "send",
  "account": "accepted",
  "domain": "sandbox.email-validation.org",
  "did_you_mean": null,
  "free_email": false,
  "role_account": false,
  "disposable": false,
  "catch_all_domain": false,
  "mx_found": true,
  "mx_record": "mx.sandbox.email-validation.org",
  "smtp_provider": "other",
  "domain_age_days": 3650,
  "processed_at": "2026-11-02T09:30:00.000Z",
  "credits_used": 0,
  "request_id": "req_7Hq2LmX9cV4bN8tR1zK6wD"
}
```

`accepted@sandbox.email-validation.org` is a free [test address](https://email-validation.org/docs/test-addresses/); every reason has one, so you can
build and test your integration without spending credits.

## Results you can act on

| Status | What it means | Default action | Credit |
|---|---|---|---|
| [`deliverable`](https://email-validation.org/docs/statuses/deliverable/) | The mailbox exists and accepted our check, so mail sent to it should arrive. | `send` (send) | 1 |
| [`undeliverable`](https://email-validation.org/docs/statuses/undeliverable/) | Mail sent to this address will not arrive, so it should come off your list. | `remove` (remove) | 1 |
| [`risky`](https://email-validation.org/docs/statuses/risky/) | The address may accept mail, but sending to it can hurt your bounce rate or sender reputation. | `send_with_caution` (send with caution) | 1 |
| [`unknown`](https://email-validation.org/docs/statuses/unknown/) | We could not get a definite answer this time, so no credit is used and a later retry often succeeds. | `retry_later` (retry later) | Free |

Each status comes with a [reason](https://email-validation.org/docs/statuses/) such as `no_mailbox`, `catch_all` or `disposable`, flags for
free, role, disposable and catch-all addresses, a typo suggestion when one applies, and the domain's mail server and
provider.

## What you get

- **Real-time checks** with `POST /v1/validate`: up to 500 requests per second on paid accounts, and a
  `timeout` you choose between 5 and 15 seconds. Checks that run out of time are free.
- **Bulk jobs** for lists of up to 1,000,000 rows, with filtered CSV downloads and
  [webhooks](https://email-validation.org/docs/webhooks/) when they finish. See the [bulk jobs API](https://email-validation.org/docs/api/bulk/).
- **Official SDKs** for [JavaScript and TypeScript](https://email-validation.org/docs/sdks/javascript/) and [Python](https://email-validation.org/docs/sdks/python/), with
  retries and typed errors, plus [code samples](https://email-validation.org/docs/code-samples/) for curl, PHP, Ruby, Go, Java, C# and Rust.
- **An OpenAPI 3.1 document** at [https://api.email-validation.org/openapi.json](https://api.email-validation.org/openapi.json) and a generated
  [API reference](https://email-validation.org/docs/api-reference/).
- **An MCP server** so AI agents can use the same checks with your key: [MCP setup](https://email-validation.org/docs/mcp/).
- **Key controls:** scopes, per-key daily credit caps and rate limits, browser-origin lists and key rolling. See
  [authentication](https://email-validation.org/docs/authentication/).

## Pricing

One credit per result, bought in one-time packs that last 24 months, down to $0.45 per
1,000 checks with the 1,000,000-credit pack. Unknown results, errors and test addresses are free. See
[pricing](https://email-validation.org/pricing/) and [credits and billing](https://email-validation.org/docs/credits-and-billing/).

## Frequently asked questions

### How much does the API cost?

One credit per result. Credits come in one-time packs, from $35 for 10,000 to $450 for 1,000,000, and last 24 months. Results with the status unknown, requests that end in an error and test addresses are free.

### Is there a free trial?

Every new account gets 500 free credits, with no card needed. Test addresses on the sandbox domain never cost a credit, so you can build your integration without spending any.

### What are the rate limits?

Paid accounts can send up to 500 validation requests per second; accounts without a purchase up to 20. Each check takes at most 15 seconds; slower checks return unknown and are free.

### Which languages are supported?

The API is HTTPS and JSON, described by an OpenAPI 3.1 document. There are official SDKs for JavaScript/TypeScript and Python, and code samples for curl, JavaScript, TypeScript, Python, PHP, Ruby, Go, Java, C# and Rust.

### Can I validate whole lists through the API?

Yes. A bulk job takes a CSV or text file of up to 100 MB, or a JSON list of up to 100,000 addresses, and lists of up to 1,000,000 rows overall. You download the results as CSV and can get a webhook when the job ends.

### Do you send an email to the addresses I check?

No. A check talks to the receiving mail server without sending a message. Addresses you check through the API are not stored in a check history.

### Can AI agents use the API?

Yes. The MCP server offers single checks, credit balance and bulk jobs (up to 10,000 addresses per call) as tools, with your API key and the same credits and limits as the REST API.
