API Documentation v1
Verify email addresses in real-time using SMTP probing, MX analysis, and catch-all detection. Integrates in minutes with any language.
Authentication
Every API request requires your API key. Pass it in the Authorization header:
Authorization: Bearer ev_live_YOUR_API_KEY_HERE
Alternatively, use the X-API-Key header:
X-API-Key: ev_live_YOUR_API_KEY_HERE
Base URL
https://your-domain.com/api/v1
All endpoints below are relative to this base URL.
Rate Limits
| Plan | Requests/min | Monthly Included | Overage |
|---|---|---|---|
| Free | 10 | 100 | Hard cap |
| Starter ($29/mo) | 60 | 5,000 | $0.008/each |
| Pro ($99/mo) | 300 | 25,000 | $0.005/each |
| Enterprise ($299/mo) | 1,000 | 100,000 | $0.003/each |
When you hit your rate limit, the API returns 429 Too Many Requests with a Retry-After header.
Error Handling
Errors return a JSON body with error and message fields:
{
"error": "usage_limit_reached",
"message": "Monthly limit reached (100 verifications). Upgrade to continue.",
"used": 100,
"limit": 100
}
| Status | Meaning |
|---|---|
400 | Bad request (missing/invalid params) |
401 | Invalid or missing API key |
402 | Monthly usage limit reached |
403 | Forbidden (email not verified, account suspended) |
429 | Rate limit exceeded |
500 | Server error |
Verify Single Email
POST /api/v1/verify
Verify one email address in real-time. Response takes 2-15 seconds depending on the mail server.
Request
curl -X POST https://your-domain.com/api/v1/verify \
-H "Authorization: Bearer ev_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"email": "john@example.com"}'
| Field | Type | Required | Description |
|---|---|---|---|
email | string | Yes | Email address to verify (max 320 chars) |
refresh | boolean | No | Set true to skip cache and force a fresh SMTP probe |
Response (200 OK)
{
"email": "john@example.com",
"domain": "example.com",
"score": 92,
"tier": "deliverable",
"tierLabel": "OK",
"result": "ok",
"quality": "deliverable",
"provider": "Google Workspace",
"isRole": false,
"isDisposable": false,
"mx": [
{ "exchange": "aspmx.l.google.com", "priority": 1 }
],
"smtp": {
"connected": true,
"mailboxExists": true,
"responseCode": 250,
"latencyMs": 342
},
"catchAll": {
"isCatchAll": false
},
"spf": true,
"dmarc": true,
"verifiedAt": "2026-05-15T10:30:00.000Z",
"cached": false
}
Verify Bulk (Async)
POST /api/v1/verify/bulk
Submit up to 50,000 emails for asynchronous verification. Returns a job ID to poll for results.
Request
curl -X POST https://your-domain.com/api/v1/verify/bulk \
-H "Authorization: Bearer ev_live_YOUR_KEY" \
-H "Content-Type: application/json" \
-d '{"emails": ["alice@gmail.com", "bob@yahoo.com", "invalid@fake.xyz"]}'
Response (202 Accepted)
{
"jobId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "processing",
"total": 3,
"message": "Job created. Poll GET /api/v1/jobs/{jobId} for status."
}
Job Status
GET /api/v1/jobs/{jobId}
Poll the status of a bulk verification job.
curl https://your-domain.com/api/v1/jobs/a1b2c3d4-... \ -H "Authorization: Bearer ev_live_YOUR_KEY"
Response
{
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"status": "completed", // queued | processing | completed | failed
"total_emails": 3,
"completed": 3,
"deliverable": 2,
"risky": 0,
"undeliverable": 1,
"created_at": "2026-05-15T10:30:00.000Z"
}
Job Results
GET /api/v1/jobs/{jobId}/results
Get paginated verification results for a completed job.
curl "https://your-domain.com/api/v1/jobs/a1b2c3d4-.../results?page=1&limit=100" \ -H "Authorization: Bearer ev_live_YOUR_KEY"
| Query Param | Default | Description |
|---|---|---|
page | 1 | Page number |
limit | 100 | Results per page (max 1000) |
tier | all | Filter by tier: deliverable, risky, undeliverable |
Download CSV
GET /api/v1/jobs/{jobId}/download
Download all results as a CSV file.
curl -O https://your-domain.com/api/v1/jobs/a1b2c3d4-.../download \ -H "Authorization: Bearer ev_live_YOUR_KEY"
Account Info
GET /api/v1/account
Get your current plan, usage, and remaining quota.
curl https://your-domain.com/api/v1/account \ -H "Authorization: Bearer ev_live_YOUR_KEY"
Response
{
"plan": "free",
"planName": "Free",
"month": "2026-05",
"used": 42,
"included": 100,
"remaining": 58,
"overage": 0,
"overageRate": null,
"rateLimit": 10
}
Result Tiers
Every verification returns a tier and score (0-100):
| Tier | Result | Score Range | Meaning | Action |
|---|---|---|---|---|
| deliverable | ok |
80-100 | Mailbox exists, SMTP confirmed | Safe to send |
| risky | risky / catch_all |
40-79 | Catch-all domain, role address, or inconclusive | Send with caution |
| undeliverable | invalid |
0-39 | Mailbox doesn't exist, domain dead, or hard bounce | Do not send |
| unknown | unknown |
varies | Server unreachable, timeout, or blocked | Retry later |
Response Fields
| Field | Type | Description |
|---|---|---|
email | string | Normalized email address |
domain | string | Domain part of the email |
score | number | Confidence score 0-100 |
tier | string | deliverable | risky | undeliverable | unknown |
result | string | ok | catch_all | risky | invalid | unknown |
provider | string | Email provider (Google, Microsoft 365, etc.) |
isRole | boolean | True if role-based (info@, admin@, etc.) |
isDisposable | boolean | True if disposable/temporary email |
mx | array | MX records for the domain |
smtp.connected | boolean | Whether SMTP connection was established |
smtp.mailboxExists | boolean | Whether RCPT TO was accepted |
smtp.responseCode | number | SMTP response code (250, 550, etc.) |
smtp.latencyMs | number | SMTP probe round-trip time in ms |
catchAll.isCatchAll | boolean | True if domain accepts all addresses |
spf | boolean | Whether domain has SPF record |
dmarc | boolean | Whether domain has DMARC record |
verifiedAt | string | ISO 8601 timestamp of verification |
cached | boolean | True if result was served from cache |
Plans & Pricing
View available plans programmatically:
GET /api/v1/plans (no auth required)
Code Examples
cURL
# Single verification curl -X POST https://your-domain.com/api/v1/verify \ -H "Authorization: Bearer ev_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"email": "test@gmail.com"}' # Bulk verification curl -X POST https://your-domain.com/api/v1/verify/bulk \ -H "Authorization: Bearer ev_live_YOUR_KEY" \ -H "Content-Type: application/json" \ -d '{"emails": ["a@gmail.com", "b@yahoo.com"]}' # Check job status curl https://your-domain.com/api/v1/jobs/JOB_ID \ -H "Authorization: Bearer ev_live_YOUR_KEY"
Python
# pip install requests import requests API_KEY = "ev_live_YOUR_KEY" BASE = "https://your-domain.com/api/v1" headers = {"Authorization": f"Bearer {API_KEY}"} # Single verify r = requests.post(f"{BASE}/verify", json={"email": "test@gmail.com"}, headers=headers) data = r.json() print(f"{data['email']} -> {data['tier']} (score: {data['score']})") # Bulk verify r = requests.post(f"{BASE}/verify/bulk", json={"emails": ["a@gmail.com", "b@yahoo.com"]}, headers=headers) job_id = r.json()["jobId"] print(f"Job submitted: {job_id}") # Poll until complete import time while True: status = requests.get(f"{BASE}/jobs/{job_id}", headers=headers).json() if status["status"] == "completed": break time.sleep(5) # Get results results = requests.get(f"{BASE}/jobs/{job_id}/results", headers=headers).json()
JavaScript / Node.js
const API_KEY = "ev_live_YOUR_KEY";
const BASE = "https://your-domain.com/api/v1";
const headers = {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json"
};
// Single verify
const res = await fetch(`${BASE}/verify`, {
method: "POST",
headers,
body: JSON.stringify({ email: "test@gmail.com" })
});
const data = await res.json();
console.log(`${data.email} -> ${data.tier} (score: ${data.score})`);
// Bulk verify
const bulk = await fetch(`${BASE}/verify/bulk`, {
method: "POST",
headers,
body: JSON.stringify({ emails: ["a@gmail.com", "b@yahoo.com"] })
});
const { jobId } = await bulk.json();
// Poll until complete
let status;
do {
await new Promise(r => setTimeout(r, 5000));
const poll = await fetch(`${BASE}/jobs/${jobId}`, { headers });
status = await poll.json();
} while (status.status !== "completed");
// Get results
const results = await fetch(`${BASE}/jobs/${jobId}/results`, { headers });
console.log(await results.json());
PHP
$apiKey = "ev_live_YOUR_KEY";
$base = "https://your-domain.com/api/v1";
$ch = curl_init("$base/verify");
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer $apiKey",
"Content-Type: application/json"
],
CURLOPT_POSTFIELDS => json_encode(["email" => "test@gmail.com"])
]);
$response = json_decode(curl_exec($ch), true);
echo "{$response['email']} -> {$response['tier']} (score: {$response['score']})\n";
Need help? Contact support or check the Dashboard