One POST request. Nothing to install.
Send an address, get back a status, a score, and the individual checks that produced them — syntax, MX, mailbox probe, disposable, role, catch-all, typo. Write your own policy on top of the signals instead of trusting somebody else's verdict.
What we found in 807,203 verifications · H1 2026
75.9%
Deliverable
10.2%
Invalid
8.7%
Risky
8.1%
Catch-all
80% of the lists we processed were at least 20% unusable. See the full benchmark data
Most verification APIs hand you a single word and ask you to trust it. Here is what is in the response and what surrounds it.
POST JSON, put your key in an X-API-Key header, read JSON back. Whatever HTTP client is already in your project works — nothing new in your dependency tree, nothing to keep updated.
The OpenAPI document lives at clearbounce.net/openapi.json. Import it into Postman or Insomnia, or point a client generator at it and get a typed client for your language.
Every result carries checks.isDisposable, isRoleBased, isFreeProvider, isCatchAll, hasTypo and the raw SMTP outcome, plus a riskFactors array explaining the score.
401 for a bad key, 402 when the balance runs out, 429 with a Retry-After header when you exceed 100 requests a minute. Errors are JSON with a stable code field, not an HTML page.
The same credentials verify one address at a signup form and a million from a file. Bulk is three calls — upload, poll status, download results — not a separate product with separate billing.
Buy once and spend them whenever the traffic arrives. There is no monthly minimum keeping the key alive and no annual burn date, so a quiet quarter costs you nothing.
One call inside your registration handler is enough to stop a throwaway mailbox before it becomes a row in your users table. The response tells you which rule tripped, so you can return a message the user can act on rather than a generic rejection.
A real mailbox probe runs behind every result, which is why a call takes around a second rather than milliseconds — a cache lookup answers faster and tells you far less
Some providers greylist or tarpit deliberately, so a minority of calls run long. If you would rather not hold the request, verify right after the record is written and flag it
checks.hasTypo comes back as an object with original, suggested and confidence, so you can offer "did you mean gmail.com?" instead of just refusing
// app/api/register.ts
const res = await fetch('https://clearbounce.net/api/v1/verify', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.CB_KEY,
},
body: JSON.stringify({ email }),
});
const { data } = await res.json();
// data.status -> deliverable | undeliverable | risky | unknown
if (data.status === 'undeliverable' || data.checks.isDisposable) {
return reply.code(422).send({
error: 'Please use a valid email address.',
suggestion: data.checks.hasTypo?.suggested ?? null,
});
}
// ...create the account
The hard part of integrating a verification API is deciding what to do with the middle of the range. This is the policy we would write.
| status | What it means | Reasonable handling |
|---|---|---|
| deliverable | The mailbox answered and accepted the address. | Accept it. This is the only result you can treat as confirmed. |
| undeliverable | The domain, the MX record or the mailbox itself rejected it. | Block it at the form, suppress it in a list. Sending here produces a hard bounce. |
| risky | Reachable, but with a reason to hesitate: disposable, role-based, catch-all, a likely typo, or an ambiguous answer from the provider. | We do not recommend sending. At a signup form, decide per sub-status — a typo deserves a prompt, a disposable domain deserves a rejection. |
| unknown | The provider would not give a usable answer within the time available — greylisting, a tarpit, or a temporary failure. | Retry later rather than deciding now. Do not treat it as a rejection. |
The exact reason is in subStatus, the numeric summary is in score (0-100), and riskFactors lists the specific signals in plain English.
When the list is already in a database or a CSV, you do not want to loop the single endpoint a million times. Upload the file, poll the job, download the results — the job runs across our own probe network and returns every address labelled.
POST /api/v1/bulk/upload takes the file and hands back a job id
GET /api/v1/bulk/status/{jobId} reports progress while it runs
GET /api/v1/bulk/results/{jobId} returns every address with the same result shape as the single endpoint
An API is only as good as what you can see when something looks wrong at two in the morning.
Single verifications and bulk jobs both land in your account history with the full result, so you can check what we actually returned instead of reconstructing it from your own logs.
Create and revoke API keys from the dashboard. The rate limit is counted per key, so a runaway script in staging cannot starve production.
If the integration is not worth writing, there is a WordPress plugin and Zapier and Make connectors that call the same endpoint.
Statuses and sub-statuses follow the same vocabulary the industry already uses, so swapping a provider in or out does not mean rewriting the branch that reads them.
Connect your platform and verify the list where it already lives, or use the API and skip the export entirely.
Verification demand is rarely flat. It spikes when you migrate, when a season starts, when a list arrives. Pricing that assumes a steady monthly volume charges you for the quiet months too.
Credits never expire. Buy for the spike, use the balance whenever it comes up next.
From $4 per 1,000 emails pay-as-you-go, or save 20% on a subscription if your volume is predictable.
100 free credits on signup, no credit card required.
Start free
100 credits
Enough to verify a real sample of your list and see the result breakdown before you spend anything.
Create a free account Compare all plansNo, and that is deliberate. The API is one POST endpoint with a JSON body and a header — a wrapper library would be more code to keep in sync than the request it replaces. If you want a typed client, generate one from clearbounce.net/openapi.json; the docs carry copy-paste examples for cURL, JavaScript, Python and PHP.
A call typically completes in about a second, because a real SMTP conversation happens behind it. Providers that greylist or deliberately slow down probes take longer, so build for a response that occasionally runs long: either verify inside the form submit and accept the wait, or verify immediately after the record is created and flag it.
A hundred requests a minute per API key. Responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset, and a 429 includes Retry-After. If your volume needs more than that, get in touch rather than sharding keys.
Yes — a single verification costs one credit whatever it returns, because the work happened either way. In a bulk job the accounting is kinder: duplicate addresses inside the same list are charged once, and addresses where our probes were temporarily blocked by the provider, or where the provider refuses verification traffic outright, are refunded automatically.
Email lists, verification results and bulk job data are deleted automatically after 60 days. That is written into our privacy policy, not just our intentions.
Every new account starts with 100 free credits and no card on file, which is enough to run a realistic integration test against real addresses. There is no fake sandbox mode — you are testing the same code path production will use.
Marketers
Know what is on the list before you commit your sending reputation to it.
Enterprises
High volume, a published DPA, and no twelve-month commitment.
Partners
Recommend ClearBounce and earn a recurring share of every account you bring.
Non-Profits
Free verification credits for registered nonprofits, because the donor list matters.
100 free credits, no credit card. Verify a real sample and see the deliverable, risky and catch-all breakdown for yourself.