Email Validation API
API reference
Email Validation HTTP endpoints on api.syndaq.com.
All Email Validation endpoints are served from https://api.syndaq.com/v1/emailval/.
Authenticated requests require a valid Email Validation key. Lookup routes require your ev_sec_ secret key.
Endpoints overview
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /v1/emailval/lookup | Secret key | Lookup by ?email= query parameter |
| GET | /v1/emailval/lookup/{email} | Secret key | Lookup by email in the URL path (URL-encoded) |
| GET | /v1/emailval/status | Public or secret key | Plan limits and quota snapshot |
Response headers
Successful and error responses may include:
| Header | Description |
|---|---|
X-Request-Id | Unique ID for support and log correlation |
X-RateLimit-Limit | Plan requests per minute for this key |
X-RateLimit-Remaining | Requests left in the current minute window |
X-RateLimit-Reset | Unix timestamp when the minute window resets |
X-Quota-Limit | Monthly quota for the subscription |
X-Quota-Remaining | Lookups left this calendar month (UTC) |
X-Quota-Period | Current quota month (YYYY-MM) |
Retry-After | Seconds to wait after HTTP 429 |
GET /v1/emailval/lookup
Validates format, disposable domain status, and MX presence for a single email address.
Request
Pass the target email using one of these forms:
GET /v1/emailval/lookup/user%40example.com
GET /v1/emailval/lookup?email=user%40example.com
Always URL-encode @ and other reserved characters when using the path form.
Headers:
Authorization: Bearer ev_sec_YOUR_SECRET_KEY
v1 scope
v1 checks format, disposable domains, and MX records only. It does not perform SMTP mailbox verification, catch-all detection, or deliverability scoring. Every successful response includes limits_note stating this clearly.
Success response (200)
{
"success": true,
"email": "[email protected]",
"domain": "example.com",
"cached": true,
"fetched_at": "2026-07-15 12:00:00.000",
"valid_format": true,
"disposable": false,
"has_mx": true,
"mx": [
"10 mx.example.com"
],
"risk": {
"level": "low",
"reasons": []
},
"limits_note": "v1 checks format, disposable domains, and MX records only — not mailbox existence or deliverability.",
"request_id": "e6d04020be9b57b1e1069d6e483c0443"
}
Example of a high-risk disposable address:
{
"success": true,
"email": "[email protected]",
"domain": "mailinator.com",
"valid_format": true,
"disposable": true,
"has_mx": true,
"mx": [
"10 mail.mailinator.com"
],
"risk": {
"level": "high",
"reasons": [
"disposable_domain"
]
},
"limits_note": "v1 checks format, disposable domains, and MX records only — not mailbox existence or deliverability."
}
Risk levels
| Level | Typical causes |
|---|---|
high | Disposable domain and/or no MX records |
medium | Role-like local part (admin, info, noreply, and similar) |
low | Valid format, not disposable, MX present, non-role local part |
Response fields
| Field | Type | Description |
|---|---|---|
email | string | Normalized email address |
domain | string | Domain portion of the email |
cached | boolean | true when Syndaq already holds a recent result for this lookup |
fetched_at | string | When this result was last retrieved |
valid_format | boolean | Whether the address passed format normalization |
disposable | boolean | Whether the domain matches a known disposable list |
has_mx | boolean | Whether MX records were found for the domain |
mx | array | MX records as priority + host strings |
risk.level | string | low, medium, or high |
risk.reasons | array | Machine-readable reason codes |
limits_note | string | Explicit reminder of v1 capabilities |
GET /v1/emailval/status
Returns key status, plan limits, and quota usage without performing a lookup.
Request
GET /v1/emailval/status
Authorization: Bearer ev_sec_YOUR_SECRET_KEY
The public key (ev_pub_) is accepted on this route.
Success response (200)
{
"success": true,
"status": "active",
"product": "emailval",
"plan": "starter",
"rate_limit_per_minute": 120,
"monthly_quota": 10000,
"quota_unlimited": false,
"quota_remaining": 9842,
"quota_period": "2026-07",
"database_records": 64000
}
Errors
Failed requests return JSON with success: false, error, error_code, and usually request_id.
| HTTP | error_code | Typical cause |
|---|---|---|
| 400 | invalid_email | Missing or empty email parameter |
| 401 | missing_credentials | No API key provided |
| 401 | invalid_api_key | Unknown, inactive, or revoked key |
| 401 | wrong_key_type | Public key used on a lookup endpoint |
| 403 | ip_not_allowed | Caller IP not on the key allowlist |
| 429 | rate_limit_exceeded | Per-minute limit exceeded |
| 429 | quota_exceeded | Monthly quota exhausted |
| 502 | lookup_failed | Temporary MX / disposable list failure |
| 500 | internal_error | Unexpected server error |
Addresses that fail format checks usually still return HTTP 200 with valid_format: false and an elevated risk object, rather than a 400, so your application can render a consistent UI.
Handle non-200 responses in your application and retry transient errors with exponential backoff.