# REST API

> Complete EmailVerify Pro REST API guide: authentication, single and bulk email verification, catch-all resolution, email finder, suppression lists, and webhooks across 152 endpoints.

Source: https://emailverifypro.com/docs/api

The REST API is the foundation — the CLI, the SDKs and the MCP server are all thin
wrappers over it. Base URL:

```
https://emailverifypro.com
```

All responses are JSON. All requests that send a body use `Content-Type: application/json`.
There are 152 endpoints; this page covers the ones almost everybody uses. The
[full reference](https://emailverifypro.com/docs/endpoints) lists the rest, and
[`https://emailverifypro.com/openapi.json`](https://emailverifypro.com/openapi.json) is the machine-readable spec.

## Authentication

Pass your key in the `X-API-Key` header:

```bash
curl -H "X-API-Key: evp_your_key" "https://emailverifypro.com/validate?email=a@example.com"
```

Or as a query parameter, where headers are awkward:

```bash
curl "https://emailverifypro.com/validate?email=a@example.com&api_key=evp_your_key"
```

> **Warning.** A key in a query string ends up in browser history, proxy logs and server
> access logs. Prefer the header.

Requests without a key still work and are rate limited by IP. A key raises your limits
and attributes usage to your account. See [API keys](https://emailverifypro.com/docs/api-keys).

## Verify a single address

### `GET /validate`

The workhorse. Every signal layer, one address.

```bash
curl -H "X-API-Key: evp_your_key" \
  "https://emailverifypro.com/validate?email=someone@example.com"
```

| Parameter | Type | Default | Purpose |
|---|---|---|---|
| `email` | string | *required* | The address to verify |
| `smtp` | bool | `true` | Perform the live SMTP probe. Turning this off is much faster but far less accurate |
| `rbl` | bool | `true` | Check the MX IP against blacklists |
| `gravatar` | bool | `true` | Look for a Gravatar as a signal the address is real |
| `breach` | bool | `false` | Check breach databases — strong evidence an address existed |
| `web_presence` | bool | `true` | Look for the address on the domain's website |
| `domain_age` | bool | `true` | Domain registration age; very new domains are riskier |
| `enrich` | bool | `false` | Add the ML prediction and an activity score |
| `suppression` | bool | `true` | Check your suppression list first |

### `POST /validate`

Same thing with a JSON body — use it when the address may contain characters awkward in
a URL.

```bash
curl -X POST https://emailverifypro.com/validate \
  -H "X-API-Key: evp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"email":"someone@example.com","breach":true,"enrich":true}'
```

### The response

```json
{
  "email": "someone@example.com",
  "status": "valid",
  "sub_status": "mailbox_verified",
  "confidence_score": 99,
  "deliverability": "deliverable",
  "deliverability_score": {
    "score": 96,
    "grade": "A+",
    "band": "excellent",
    "can_send": true,
    "recommendation": "Send",
    "primary_risk": null,
    "email_type": "personal",
    "breakdown": {
      "mx_found": 10,
      "smtp_valid": 25,
      "corporate_domain": 5,
      "name_pattern": 5
    }
  },
  "account": "someone",
  "domain": "example.com",
  "mx_found": true,
  "mx_records": ["aspmx.l.google.com"],
  "smtp_provider": "google",
  "smtp_response_code": "250",
  "catch_all": false,
  "is_disposable": false,
  "is_role": false,
  "is_free": false,
  "did_you_mean": null
}
```

| Field | Why you care |
|---|---|
| `deliverability_score.can_send` | **The decision.** Boolean, already weighs every signal |
| `deliverability_score.score` | 0–100, if you want your own threshold |
| `status` | Raw SMTP verdict: `valid`, `invalid`, `accept_all`, `unknown` |
| `sub_status` | Why — e.g. `mailbox_verified`, `mailbox_not_found`, `catch_all_address` |
| `catch_all` | The domain accepts everything; per-address proof is impossible |
| `is_disposable` | Temporary/burner provider |
| `is_role` | `support@`, `info@`, `sales@` — real, but not a person |
| `did_you_mean` | Typo suggestion, e.g. `gmial.com` → `gmail.com` |

## Verify many addresses

### `POST /validate/bulk` — synchronous, up to 100

```bash
curl -X POST https://emailverifypro.com/validate/bulk \
  -H "X-API-Key: evp_your_key" \
  -H "Content-Type: application/json" \
  -d '{
    "emails": ["a@example.com", "b@example.com"],
    "deduplicate": true,
    "check_suppression": true,
    "max_concurrent": 10
  }'
```

```json
{
  "total": 2,
  "processing_time_ms": 8652,
  "summary": {"valid": 1, "invalid": 1},
  "results": [
    {"email": "a@example.com", "status": "valid", "confidence_score": 95},
    {"email": "b@example.com", "status": "invalid", "sub_status": "mailbox_not_found"}
  ]
}
```

> The whole call blocks until every address finishes, so it takes as long as the slowest
> one. For more than about 25 addresses, prefer the async endpoint.

### `POST /validate/bulk/async` — a job you poll

```bash
curl -X POST https://emailverifypro.com/validate/bulk/async \
  -H "X-API-Key: evp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"emails": ["a@example.com", "b@example.com"]}'
```

```json
{"job_id": "job_a1b2c3", "status": "queued", "total": 2}
```

```bash
curl -H "X-API-Key: evp_your_key" https://emailverifypro.com/jobs/job_a1b2c3
```

Poll every few seconds until `status` is `completed`, then read `results`.
`GET /jobs/{job_id}/dead-letter` lists addresses that failed permanently, and
`POST /jobs/{job_id}/retry-dead-letter` re-queues them.

### `POST /validate/bulk/turbo`

Same shape as `/validate/bulk`, tuned for throughput over per-address depth. Use it when
you are cleaning a very large list and can accept slightly lower confidence.

## Faster, cheaper checks

| Endpoint | Cost | Use when |
|---|---|---|
| `GET /validate/syntax` | free, instant | Form validation — is it even a well-formed address? |
| `GET /validate/quick` | fast | DNS and MX only, no SMTP probe |
| `GET /validate/fast` | fast | Cached result if present, otherwise a shallow check |
| `GET /validate` | full | You are about to send mail to this address |

```bash
curl "https://emailverifypro.com/validate/syntax?email=not-an-email"
```

```json
{"email": "not-an-email", "valid": false, "normalized": "", "did_you_mean": null}
```

## Catch-all domains

A catch-all domain accepts mail for *every* address, so no verifier on earth can prove a
specific mailbox exists there over SMTP. When `status` is `accept_all`, resolve it with
additional signals:

```bash
curl -X POST https://emailverifypro.com/resolve-catchall \
  -H "X-API-Key: evp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"email":"jane@catchall-example.com"}'
```

This runs a nine-signal pipeline — Microsoft credential probing, LinkedIn presence,
breach records, Gravatar, domain cohort behaviour and more — and returns a resolved
verdict where it can.

> **Warning.** Treat `accept_all` as its own risk tier, not as a pass or a fail. Roughly
> a quarter of business domains are catch-all.

## Finding an address

```bash
curl -X POST https://emailverifypro.com/find-email \
  -H "X-API-Key: evp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"domain":"example.com","first_name":"Jane","last_name":"Doe"}'
```

Detects the domain's naming convention (`first.last@`, `flast@`, `first@`) from known
addresses, then constructs and verifies the most likely candidates.

Related: `GET /domain-formats/{domain}` returns the learned pattern on its own.

## Suppression list

Stop sending to addresses that bounced, complained or unsubscribed.

```bash
curl -X POST https://emailverifypro.com/suppression/add \
  -H "X-API-Key: evp_your_key" \
  -H "Content-Type: application/json" \
  -d '{"email":"unsubscribed@example.com","reason":"unsubscribe"}'

curl -H "X-API-Key: evp_your_key" \
  "https://emailverifypro.com/suppression/check?email=unsubscribed@example.com"
```

With `check_suppression: true` (the default), bulk verification skips suppressed
addresses automatically.

## Feedback improves accuracy

Report real outcomes and the model learns from them:

```bash
curl -X POST https://emailverifypro.com/bounce \
  -H "Content-Type: application/json" \
  -d '{"email":"bounced@example.com","bounce_type":"hard"}'

curl -X POST https://emailverifypro.com/delivered \
  -H "Content-Type: application/json" \
  -d '{"email":"delivered@example.com"}'
```

Your ESP can post these directly — there are ready-made receivers at
`/webhooks/sendgrid`, `/webhooks/ses`, `/webhooks/postmark` and `/webhooks/mailchimp`.

## Account and usage

```bash
curl -H "X-API-Key: evp_your_key" https://emailverifypro.com/me/usage    # quota remaining
curl -H "X-API-Key: evp_your_key" https://emailverifypro.com/me/stats    # verification statistics
curl -H "X-API-Key: evp_your_key" https://emailverifypro.com/me/recent-verifications
```

## Errors

```json
{"detail": "Invalid or revoked API key"}
```

| Code | Meaning | Do this |
|---|---|---|
| `200` | Success | — |
| `401` | Key missing, invalid or revoked | Check the key. If you just created it, wait up to 2 minutes |
| `404` | No such resource, or it belongs to another account | — |
| `422` | Invalid parameters | The body names the offending field |
| `429` | Rate limited | Back off and retry; the SDKs do this automatically |
| `500` | Server error | Retry once |

Full detail in [errors and limits](https://emailverifypro.com/docs/errors).

## Machine-readable specs

| | |
|---|---|
| OpenAPI 3.1 | [`https://emailverifypro.com/openapi.json`](https://emailverifypro.com/openapi.json) |
| Interactive explorer | [`https://emailverifypro.com/docs`](https://emailverifypro.com/docs) |
| Tooling manifest | [`https://emailverifypro.com/tooling`](https://emailverifypro.com/tooling) |
| These docs as Markdown | [`https://emailverifypro.com/llms-full.txt`](https://emailverifypro.com/llms-full.txt) |

Generate a client for any language straight from the spec:

```bash
npx @openapitools/openapi-generator-cli generate \
  -i https://emailverifypro.com/openapi.json -g go -o ./emailverify-go
```
