Real-time verification
Decide while they are still on the page.
One request per address. The response says what we found and what we suggest doing about it, so your signup form can let it through, ask for confirmation, add a step or turn it away without you writing those rules from scratch.
No message is sent to the addressStable reason codes
person@example.com
Non-interactive product preview.
{ "status": "deliverable",
"action": "allow",
"confidence": 0.92,
"checks": { "accept_all": "no",
"disposable": false },
"reason_codes": ["MX_FOUND",
"SMTP_RCPT_ACCEPTED"] }Where it goes
Four places an address enters your product.
Signup
Verify before the account exists, so a mistyped domain never becomes a support ticket.
Lead capture
Keep burner and shared-inbox addresses out of the pipeline at the form, while it still costs you nothing.
Checkout
The receipt has to arrive. Catch the typo while the customer is still there to fix it.
Internal data entry
CRM and back-office forms, where the address is typed by somebody who doesn’t own it.
The shape of an integration
One call, one decision.
- 01
Somebody types an address
In your form, on your domain.
- 02
Your server calls the API
Server-side, with your key. It never reaches the browser.
- 03
We gather the evidence
Syntax, the domain, its routing, and a mailbox probe where that is worth doing.
- 04
The response comes back
Status, recommendation, checks and reason codes. Or
pending, with an interval to come back on. - 05
Your flow decides
Let them in, ask them to confirm, add a step, or stop there. Your rules, if you would rather.
The response
Status is what we saw. Action is what we suggest.
They are two separate fields on purpose. Different products can apply completely different rules to identical evidence, and nothing about the probing changes.
| Status | Meaning | Recommended action |
|---|---|---|
| deliverable | The mailbox took it, and nothing was flagged | allow |
| risky | It may well work, but the evidence is thin | challenge |
| undeliverable | A hard failure, and it won’t change | reject |
| unknown | The mail server wouldn’t say | allow_with_email_confirmation |
| pending | The slower evidence is still coming | poll after retry_after_ms |
Short of a hard failure, everything here leans towards letting the person through to a confirmation email. That email is the only thing that ever really proves somebody holds a mailbox.
Integration paths
Three ways in, depending on who is building it.
Server-side API
Best for product teams that already have a backend.
Effort one endpoint, one credential.
Security the key stays on your server; anonymous access is not offered.
Automation platform
Best for teams without engineering time.
Effort connect the account, map one field.
Security the credential lives in the platform’s vault.
Batch import
Best for periodic cleaning of a store you already own.
Effort upload and export, no code.
Security same processing and retention as everything else.
We will link the documentation here the day the public developer portal goes live. Until then there is nothing to link to, and we would rather say so than point you at a page that does not exist.
Timing, honestly
Not instant, and we’re not going to call it that.
Answers that come from syntax, DNS and routing arrive quickly. Answers that need a mailbox probe depend on somebody else picking up, and a few providers delay first contact on purpose.
Fast path
Parse failures, domains that don’t exist and null-MX declarations are all settled without contacting anybody.
Probe path
Where a probe is warranted the answer may return as pending with an explicit retry_after_ms, so polling is bounded rather than blind.
Published figures
Median and p95 latency, rate limits and uptime: [MEASURED FIGURES]. They go up here once they have been measured, and not a day earlier.
Handling uncertainty
What happens when the answer isn’t clean.
A green tick and a red cross are the easy part. What tells you whether a verifier is any good is what it does when SMTP won’t give a straight answer.
Catch-all domains
A domain that accepts every recipient tells you nothing about the specific mailbox. Acceptance is scored down and reported as risky with ACCEPT_ALL_DOMAIN, never promoted to deliverable.
Greylisting and throttling
A temporary refusal is not a rejection. It is recorded as its own reason code so a retry can be scheduled instead of a person being wrongly turned away.
Timeouts
A connection nobody answers gives you unknown, never undeliverable. No answer is not the same as a no.
Provider policy blocks
Some providers refuse probes on principle, and some of those refusals are aimed at our sending identity rather than at your recipient. We track those separately, because they say nothing at all about the address.
Credentials and abuse
Server-side by design.
Keys
Requests authenticate with a bearer credential. An account can hold several, each attached to a named integration, so a key can be rotated or revoked without taking down every caller. Anonymous access is not a configurable option.
Limits
Request volume is bounded per caller and per source network. A refusal carries an explicit retry hint so a client backs off rather than retrying blindly.
What never crosses the boundary
Remote server reply text stays inside the system. It leaks destination infrastructure detail, can carry untrusted control characters, and changes whenever a provider rewords a message.
Idempotency
A repeated verification of the same address returns the same conclusion under the same identifier rather than doing the work twice and writing a second record for it.
Put it in front of your signup form.
Start free. Come and talk to us when volume or procurement needs something different.