api reference

Verify that a mailbox exists

POST /v1/verify: ask the domain's mail server whether an exact address exists (no email is sent), with catch-all detection, and read status, reason and confidence.

View as Markdown

POST https://api.isbusinessemail.com/v1/verify
GET  https://api.isbusinessemail.com/v1/verify?email=…

/v1/check tells you what kind of address something is. /v1/verify answers a different question: does this exact mailbox exist and accept mail? Use it before you send to an address you collected, when cleaning a list, or when a bounce would cost you.

It works the way a sending mail server does, minus the message:

  1. Syntax, typos and the domain’s classification (the same engine as /v1/check).
  2. The domain’s MX records. No domain, no MX or a null MX means nothing can be delivered.
  3. An SMTP conversation with the primary mail server: EHLO, MAIL FROM, RCPT TO:<the address>. We read the reply and hang up. No DATA, no message, nothing reaches the person.
  4. A second RCPT TO with a random address at the same domain. If the server accepts that too, the domain is catch-all and its “yes” proves nothing.

Try it without a key on the free email verifier.

Request

curl https://api.isbusinessemail.com/v1/verify \
  -H "Authorization: Bearer $IBE_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email": "[email protected]"}'
  • Secret keys only. Publishable keys (ibe_pub_…) get 403: from a browser this endpoint would be a free tool for guessing which addresses exist, on your quota.
  • Takes seconds, not milliseconds. Most answers arrive in 1 to 5 seconds; a slow mail server can take up to about 30. Call it from a background job or after the form is submitted, not on every keystroke. Use /v1/check for instant sign-up decisions.
  • Prefer POST, so addresses stay out of URLs and logs.

Response

{
  "email": "[email protected]",
  "normalized_email": "[email protected]",
  "domain": "acme.io",
  "status": "deliverable",
  "reason": "mailbox_exists",
  "confidence": 0.97,
  "mailbox": "exists",
  "is_catch_all": false,
  "is_disposable": false,
  "is_role_account": false,
  "is_free_provider": false,
  "category": "business",
  "did_you_mean": null,
  "mail": { "provider": "google_workspace", "has_mx": true, "mx": ["aspmx.l.google.com", "alt1.aspmx.l.google.com"] },
  "smtp": { "mx_host": "aspmx.l.google.com", "stage": "rcpt", "code": 250, "enhanced_code": "2.1.5", "reply": "2.1.5 OK", "used_backup_mx": false },
  "cached": false,
  "took_ms": 1840,
  "request_id": "req_4f2a…"
}
Field Meaning
status deliverable, undeliverable, risky or unknown. Act on this.
reason Why, as a stable code: see reasons.
confidence 0 to 1. A deliverable from the primary mail server with a negative catch-all test is 0.97; the same answer from a backup MX is lower.
mailbox exists, not_found, disabled, full or unknown.
is_catch_all true when the domain accepted a random address, false when it refused one, null when we couldn’t tell.
category, is_disposable, is_role_account, is_free_provider, did_you_mean From the classification, as in /v1/check.
smtp What the mail server said: the stage we reached (greeting, ehlo, mail_from, rcpt), the reply code, the enhanced status code and the reply text with addresses and IPs removed. null when we didn’t need to ask (a cached catch-all domain, no MX).
retry_after Only when reason is greylisted: seconds after which asking again should give the real answer.
cached true when the answer came from a recent check of the same address (kept up to 24 hours; catch-all domains 12 hours, unknown answers 15 minutes).

Statuses

Status What it means What to do
deliverable The mail server accepts this address and refuses made-up ones. Send.
undeliverable No such mailbox, a disabled one, or a domain that can’t receive mail. Don’t send. Ask for another address, or fix the typo in did_you_mean.
risky It may accept mail, but nobody can confirm a person reads it: a catch-all domain, a full mailbox or a disposable inbox. Send carefully: confirm with a link, or leave out of campaigns.
unknown The mail server gave no answer we trust: greylisting, a timeout, or a refusal to answer checks. Retry later (retry_after), or fall back to a confirmation email. Never treat it as invalid.

Reasons

Reason Status Meaning
mailbox_exists deliverable 250 for the address, refusal for a random one.
accepted_unconfirmed deliverable 250 for the address; the catch-all test was inconclusive (the server hung up or deferred). Lower confidence.
invalid_syntax undeliverable Not an email address.
domain_not_found undeliverable The domain doesn’t exist (NXDOMAIN).
no_mail_server undeliverable No MX records, and either no address record to fall back to or a host there that doesn’t accept SMTP connections.
null_mx undeliverable The domain publishes MX 0 .: it accepts no mail.
dns_error undeliverable The domain’s own DNS fails (SERVFAIL), so no one can deliver to it right now.
mailbox_not_found undeliverable The server says there is no such user (5.1.1, “user unknown”, Microsoft’s 5.4.1 recipient rejection, …).
mailbox_disabled undeliverable The mailbox exists but is disabled (5.2.1).
mailbox_rejected undeliverable A plain 550/551/553 for this recipient without wording that says why. Confidence 0.8.
catch_all risky The domain also accepted a random address.
mailbox_full risky Over quota (x.2.2). Mail bounces until it is emptied.
disposable risky A temporary inbox service. We don’t probe these.
greylisted unknown The server deferred us (4xx). We ask again in the background after about 90 seconds and 5 minutes; check again after retry_after.
probe_blocked unknown The server refused to talk to us (a block list, a reputation or policy rule). Says nothing about the mailbox.
smtp_unreachable unknown No mail server answered on port 25.
smtp_timeout unknown The server was too slow, or our checks for that provider were queued too long.
smtp_rejected unknown An unclear refusal (e.g. a 554 with no explanation).
dns_unavailable unknown Our DNS lookups failed; retry.
verification_unavailable unknown Mailbox verification is switched off on our side.

How accurate is it?

For most domains, including Google Workspace, Gmail, Microsoft 365 and Outlook.com, the mail server’s answer to RCPT TO is the same answer a real message would get, so deliverable and undeliverable are reliable. We are careful in four places:

  • Catch-all domains accept everything. We detect them with the random address and answer risky, never deliverable.
  • Blocks look like rejections. A 550 can mean “no such user” or “we don’t accept your IP”. We read the enhanced status code and the wording: anything that looks like a policy or block-list refusal is unknown, so a real person’s address is never marked undeliverable because a server didn’t like the check.
  • Backup MX servers often accept any recipient because they can’t see the user directory. We only fall back to them when the primary can’t be reached, and lower the confidence when we do.
  • Greylisting defers first-time senders on purpose. We answer unknown with retry_after and retry in the background, so asking again a few minutes later returns the real answer.

A mailbox that exists today may be gone next month, and only a confirmation email proves that someone reads it. For sign-ups, a link in a welcome email remains the best final check.

Limits and cost

  • Each verification counts as 1 check against your quota (per day on the free tier, per month on paid plans). An unknown answer gives its check back, so you only pay for answers: greylisting, blocks and timeouts cost nothing (X-RateLimit-Remaining already includes the refund).
  • Verifications also have their own daily cap, because each one is an SMTP conversation from our servers: 100 a day on tier 0, 500 on tier 1, 2,000 on tier 2 and 10,000 on tier 3. Every verification counts toward it, unknown ones too. Over it you get 429 quota_exceeded. Need more? Ask.
  • The answer for the same address is cached (see cached) and doesn’t open a new SMTP conversation.
  • Verifying a whole list? Upload the CSV on your dashboard’s Bulk CSV page. It runs in your browser on the same quota, retries greylisted addresses once, and gives you your file back with the results added as columns.

Test addresses

Addresses at test.isbusinessemail.com return fixed answers, need no key and are never counted:

Address Status Reason
[email protected] deliverable mailbox_exists
[email protected] undeliverable mailbox_not_found
[email protected] undeliverable mailbox_disabled
[email protected] risky catch_all
[email protected] risky mailbox_full
[email protected] risky disposable
[email protected] unknown probe_blocked
[email protected] unknown greylisted (with retry_after)

Privacy

We never store or log the address. Results are cached under a keyed hash of the address so a repeated check doesn’t contact the mail server again. The reply text we return has addresses and IP addresses removed. See privacy and data handling.

MCP

AI assistants connected to the isBusinessEmail MCP server get the same check as the verify_email tool.