Endpoints
We expose three email validation endpoints, covering every use case :
| Endpoint | Max per call | Mode | When to use |
|---|---|---|---|
| POST /api/v1/validate | 1 email | Sync | Live forms, single lookups, auto-complete |
| POST /api/v1/validate-bulk | 200 emails | Sync | Contact sync, small list cleaning (blocking HTTP, 15-25 s) |
| POST /api/v1/validate-async | 10,000 emails | Async + webhook | Large list cleaning, background jobs, CRON jobs |
Plus an account endpoint :
| Endpoint | What |
|---|---|
| GET /api/v1/credits | Check your current credit balance (free, no credit debited) |
All validation endpoints return the same per-email result schema (valid, reason, confidence, score, details…). See sections below + Bulk validation for the batch variants.
POST /api/v1/validate
Validates a single email address, synchronously.
Request
POST /api/v1/validate
Authorization: Bearer evs_live_...
Content-Type: application/json
{
"email": "test@example.com"
}
Parameters
| Parameter | Type | Description |
|---|---|---|
email |
string | Required. The address to validate. |
The full validation pipeline (syntax, MX, SMTP, disposable, role-based, typo) is always run — no opt-in/opt-out flags. Results are cached server-side for optimal latency.
200 OK response
{
"email": "test@example.com",
"valid": true,
"reason": "ok",
"confidence": "verified",
"score": 1.0,
"details": {
"syntax": true,
"domain": "example.com",
"mx": true,
"mx_records": ["mail.example.com"],
"disposable": false,
"role_based": false,
"smtp": true,
"mx_behavior": "strict",
"possible_typo": false,
"suggested_domain": null,
"suggested_email": null,
"typo_distance": null,
"smtp_enhanced_code": "2.1.5",
"smtp_response": "250 2.1.5 OK"
},
"credits_remaining": 99940,
"cached": false
}
Top-level fields
| Field | Type | Description |
|---|---|---|
email |
string | Normalized (trim + lowercase). |
valid |
boolean | Binary verdict (see rule below). |
reason |
string | ok, syntax_invalid, mx_missing, disposable, possible_typo, smtp_reject, smtp_catch_all, smtp_anti_probe, smtp_silent, smtp_unknown. |
confidence |
string | "verified" (SMTP confirmed 250) or "basic" (SMTP not confirmed). |
score |
float (0–1) | Weighted confidence score. |
details |
object | Per-check breakdown (see below). |
credits_remaining |
int | Your wallet balance after this call. |
cached |
boolean | true if served from Redis cache. |
Details sub-fields
| Field | Type | Description |
|---|---|---|
syntax |
boolean | RFC 5322 compliance. |
domain |
string / null | Domain part. |
mx / mx_records |
boolean, string[] | MX records present, sorted by priority. |
disposable |
boolean | Known disposable mail provider. |
role_based |
boolean | Generic local part (info@, contact@...). |
smtp |
boolean / null | true if RCPT TO = 250, false if 550, null otherwise. |
mx_behavior |
string | strict, catch_all, anti_probe, silent. |
possible_typo |
boolean | Domain looks like a popular domain typo. |
suggested_domain / suggested_email |
string | Correction suggestion. |
typo_distance |
int | Levenshtein distance to suggested domain. |
smtp_enhanced_code |
string | Enhanced status code (e.g. 5.1.1, 5.2.1) when provided. |
smtp_response |
string | Raw SMTP response message (useful for advanced clients). |
valid rule
valid = true if all of the following:
syntax = truemx = truedisposable = falsesmtp ≠ false(acceptstrueornull)
role_based does not invalidate — it's informational for your business logic.
Rate limit headers
X-RateLimit-Limit: 120
X-RateLimit-Remaining: 118
X-RateLimit-Reset: 1735689600
On HTTP 429 responses, an additional Retry-After header is set.
GET /api/v1/credits
Check your current credit wallet state. Free endpoint — no credit is debited on call. Useful to monitor your balance from your app and top up automatically before running out.
Request
GET /api/v1/credits
Authorization: Bearer evs_live_...
Response 200 OK
{
"balance": 3450,
"total_purchased": 5000,
"total_consumed": 1650,
"last_topup_at": "2026-04-24 18:30:12+02",
"top_up_url": "https://email-validation-api.net/dashboard/billing"
}
| Field | Type | Description |
|---|---|---|
balance |
int | Credits currently available for validation calls |
total_purchased |
int | All-time credits purchased (excluding trial) |
total_consumed |
int | All-time credits spent on validations |
last_topup_at |
string|null | Timestamp of the last credit purchase |
top_up_url |
string | Dashboard URL to buy more credits |
Rate limit
60 calls per minute per API key. For monitoring loops, poll every 30-60 seconds at most.
Typical usage
# Shell one-liner : alert when balance < 500
BAL=$(curl -sS https://email-validation-api.net/api/v1/credits \
-H "Authorization: Bearer $EV_API_KEY" | jq -r .balance)
if [ "$BAL" -lt 500 ]; then
echo "Low credits ($BAL), top up at https://email-validation-api.net/dashboard/billing"
fi