# Errors and limits

> EmailVerify Pro status codes, rate limits per tier, timeouts, sub_status reference, and how to read an ambiguous catch-all result.

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

## Status codes

| Code | Meaning | What to do |
|---|---|---|
| `200` | Success | — |
| `401` | Key missing, invalid or revoked | Check the key. If you created it in the last two minutes, wait for it to replicate |
| `404` | No such resource — or it belongs to another account | Key endpoints return 404 rather than 403 so they never confirm that an id exists |
| `422` | Invalid parameters | The response names the offending field |
| `429` | Rate limited | Back off and retry. Both SDKs do this for you |
| `500` | Server error | Retry once. If it persists, report it |

Every error has the same shape:

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

## Rate limits

| Tier | Verifications / month | Requests / minute |
|---|---|---|
| `free` | 100 | 10 |
| `starter` | 1,000 | 30 |
| `pro` | 10,000 | 100 |
| `enterprise` | unlimited | 500 |

Requests without a key are rate limited by IP instead. Check your remaining quota:

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

Both SDKs retry `429` and `5xx` with exponential backoff, up to `max_retries` (default 3).
`401` and `403` are never retried — a bad key does not become good.

## Timeouts

> A single verification can legitimately take **30 seconds or more**. SMTP probes wait on
> remote mail servers, some of which greylist or stall deliberately. Set a client timeout
> of at least 60 seconds.

For large lists, don't hold a connection open — use the async job API:

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

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

## Reading an ambiguous result

| `status` | Confidence | Send? |
|---|---|---|
| `valid` | Mailbox confirmed to exist | Yes |
| `invalid` | Explicitly rejected by the mail server | No |
| `accept_all` | Catch-all domain — cannot be proven either way over SMTP | Judge by `can_send` |
| `unknown` | No definitive SMTP answer | Judge by `can_send` |

**Always prefer `deliverability_score.can_send` over `status`.** It already weighs
catch-all behaviour, greylisting, provider quirks, domain reputation and dozens of other
signals. A `status` of `unknown` frequently still scores above the send threshold.

> **Warning.** Catch-all domains are genuinely ambiguous. They accept mail for every
> address, so no verifier can prove a specific mailbox exists there. Treat `accept_all`
> as its own risk tier rather than as a pass or a fail — roughly a quarter of business
> domains are catch-all.

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

## Common `sub_status` values

| `sub_status` | Meaning |
|---|---|
| `mailbox_verified` | The server confirmed the mailbox |
| `mailbox_not_found` | The server said no such user |
| `catch_all_address` | The domain accepts everything |
| `google_workspace_confirmed` | Confirmed via Google Workspace |
| `m365_confirmed` | Confirmed via Microsoft 365 |
| `greylisted` | Temporarily deferred; retry later |
| `connection_failed` | Could not reach the mail server |
| `policy_rejection` | The server refused the probe on policy grounds |
| `domain_not_found` | The domain has no DNS or no MX |
| `invalid_format` | Not a well-formed address |

## Troubleshooting

### `401` on a key that was just created

Keys replicate to the verification workers on a short cycle. Wait two minutes and retry.

### `CERTIFICATE_VERIFY_FAILED` from the Python CLI or SDK

The interpreter has no CA bundle — common on python.org macOS builds. Any of these fix it:

```bash
/Applications/Python\ 3.12/Install\ Certificates.command
pip install certifi
export EMAILVERIFY_CA_BUNDLE=/etc/ssl/cert.pem
```

The client already falls back to the usual system bundles before giving up.

### Everything comes back `unknown`

Usually the destination provider is blocking probes from your region, or the domain
greylists aggressively. The deliverability score still combines every other signal, so
`can_send` remains meaningful.

### Bulk verification is slow

A bulk call takes as long as its slowest address. Above roughly 25 addresses, switch to
`POST /validate/bulk/async` and poll the job.

### The MCP server doesn't appear in my client

Validate the JSON config — a trailing comma silently breaks the whole file — then fully
restart the client. `EMAILVERIFY_API_KEY` must be in the server's `env` block; MCP servers
do not inherit your shell environment.

## Reporting a problem

Include the `email` you verified, the full JSON response, and the time. If it is
reproducible, `emailverify verify <address> --json --verbose` captures everything needed.
