Skip to content
DEVELOPER API

Email verification in one POST request.

Send an email address, get back a clear verdict, a 0–100 score, and every check we ran. Bearer-token auth, JSON in and out, no SDK required.

Authentication

Every request needs an Authorization: Bearer <token> header. Generate a token from API keys in your dashboard. Tokens are scoped to a single account.

Verify an email

POST /api/v1/verify with a JSON body containing an email. One verification spends one credit, whatever the verdict.

REQUEST · cURL
curl -X POST https://clearmx.app/api/v1/verify \
  -H "Authorization: Bearer cmx_live_your_token" \
  -H "Content-Type: application/json" \
  -d '{"email":"ana@getpalladio.com"}'
RESPONSE · 200 OK
{
  "email": "ana@getpalladio.com",
  "normalized_email": "ana@getpalladio.com",
  "result": "deliverable",
  "score": 100,
  "reason": "mailbox_exists",
  "checks": {
    "syntax": true,
    "domain": "getpalladio.com",
    "mx": true,
    "implicit_mx": false,
    "disposable": false,
    "role": false,
    "no_reply": false,
    "free": false,
    "accept_all": false,
    "tag": null,
    "irregular_characters": false,
    "provider": "google",
    "secure_gateway": null,
    "smtp": { "status": "ok", "code": 250, "accept_all": false },
    "smtp_skipped": null,
    "typo_suggestion": null
  },
  "credits_used": 1
}

Reading the result

Branch on result, not on score. result is one of four values and is always authoritative. score (0–100) is a confidence number for ranking addresses within a verdict — an unknown is deliberately scored mid-range, so a score threshold on its own would misfile it. reason gives the single deciding signal and checks gives all of them.

For completeness: once a verdict is decidable, the score thresholds are 80 for deliverable and 50 for risky. But unknown is assigned before those thresholds are ever reached, which is exactly why a score comparison is not a substitute for reading result.

deliverable additionally requires SMTP mailbox confirmation on a non-catch-all domain — a valid MX record alone caps the score at 75 and returns risky / mailbox_unconfirmed. (Breaking change note: the former valid_mx reason is retired; confirmed mailboxes return mailbox_exists.)

deliverable

A live SMTP probe confirmed this exact mailbox on a domain that is not a catch-all. Safe to send.

risky

Send at your own risk. Disposable domain, role account, catch-all domain, or a mailbox we could not confirm (mailbox_unconfirmed). Free-provider inboxes usually land here too, because those providers block mailbox probes.

undeliverable

Hard failure — it will bounce. Invalid syntax, no mail servers for the domain, or the server rejected the mailbox outright.

unknown

We could not reach a verdict: greylisting, an SMTP or DNS timeout, or a probe the server refused. Retry later; an honest unknown beats a fabricated verdict.

The checks object

Every check we ran, always present. Disposable, role and catch-all are risk signals: they deduct from the score and can never make an address deliverable.

FieldTypeMeaning
syntax boolean RFC-aware format validation. False short-circuits to undeliverable.
domain string The domain portion of the normalized address.
mx boolean Domain publishes mail servers. False short-circuits to undeliverable.
implicit_mx boolean No MX record, but an A record makes the domain mail-capable.
disposable boolean Known throwaway / temporary provider. Risk signal.
role boolean Shared role address like info@ or support@. Risk signal.
no_reply boolean Local part is noreply@ or a variant — nobody reads it.
free boolean Free mailbox provider (Gmail, Yahoo…).
accept_all boolean / null Catch-all domain: accepts every address. Risk signal. Null when catch-all detection was inconclusive.
tag string / null Plus-address tag, e.g. the "news" in jane+news@. Not stripped.
irregular_characters boolean Non-ASCII characters in the address.
provider string / null Mail provider inferred from MX hosts, e.g. google, microsoft.
secure_gateway string / null Security gateway in front of the mailbox, e.g. proofpoint. Probe results are less certain behind one.
smtp object / null Live probe: status, code, accept_all. Null when the probe was skipped.
smtp_skipped string / null Why no probe ran: disabled, no_mx, provider_blocks_probes, rate_limited.
typo_suggestion string / null A likely correction, e.g. gmial.com → gmail.com.

Errors

A syntactically invalid email is a normal result (200 + undeliverable), not an error. Errors are reserved for request problems, and every one is a JSON body with an error key. None of the responses below spends a credit.

StatusBodyWhen
401 {"error":"Unauthorized"} Missing or invalid bearer token.
402 {"error":"Out of credits","remaining":0,"upgrade_url":"…"} The account has no credits left. Buy more at upgrade_url and retry — no credit is spent and no result is kept.
422 {"error":"Email is required"} The email parameter was blank. The same status with "No account available for this token" means the token resolves to no account.
500 {"error":"Internal error"} Something went wrong on our side — safe to retry.

Volume and limits

There is no published per-key request limit today; if we introduce one we will document it here first. Two things do throttle in practice: live mailbox probes are rate-limited per destination domain (so hammering one domain returns smtp_skipped: "rate_limited" rather than a verdict), and large one-off lists are far better served by a CSV bulk import in the dashboard than by thousands of concurrent single calls. Bulk verification is dashboard-only for now — there is no bulk API endpoint yet.

API FAQ

How do I get an API token?

Create a free ClearMX account, open API keys in the dashboard, and generate a token. Each token is scoped to one account.

Is verification synchronous?

Yes. A single POST returns the full result in the response body — no polling, no callback. Syntax and DNS answers come from cache where possible; when a live mailbox probe runs it adds a round trip to the receiving mail server, bounded by a 5-second timeout.

What happens when I run out of credits?

The API returns HTTP 402 with {"error":"Out of credits"} and an upgrade_url pointing at pricing. Every new account starts with 500 free verification credits, and credits never expire.

Do you send email to the address?

No. ClearMX never sends email. The optional SMTP check talks to the receiving mail server and stops before DATA — no message is ever transmitted.

See also: Email verification API guide · Bulk verification