·6 min read·by ByeBouncer

Email validation API: understanding each result

How to use an email validation API from your server: the request, deliverable/undeliverable/undetermined results, per-check states and what to do with uncertain answers.

emailapiintegration

An email validation API is, at heart, a server-to-server request: you send an address with your private key and get back one answer per check that was run. What confuses people is rarely the call; it is the response. ByeBouncer does not return a “good or bad” verdict or a score. It returns what was checked, what could be confirmed and what stayed undetermined. This guide shows how to read each part so you can decide inside your own system.

Preparing an email validation API request

The endpoint is POST /api/v1/verify-email, with a JSON body {"email": "..."}. The key goes in the Authorization header as a Bearer token. For server-side validation use a bb_live_… key; bb_pub_… keys exist for the browser widget and are meant for that, not for your backend. For a response split by data point and without a score, add ?result_format=validation-v1 to the URL. Without it you keep the earlier format, retained for compatibility with existing integrations.

curl -X POST "https://api.byebouncer.com/api/v1/verify-email?result_format=validation-v1" \
  -H "Authorization: Bearer $BB_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"email":"person@example.com"}'

Each verification uses 1 credit, even when the result comes from cache. Keep that in mind for forms: validate once on submit, not on every keystroke. Errors are the usual ones: 400 for an invalid body, 401 for a missing or invalid key, 402 when credits run out and 429 when you exceed the request limit (with a Retry-After header).

Your serverPOST /verify-emailChecksResult per data point
The path of a request: your server sends the address with the key and receives one result per check.

Reading the result: deliverability and checks

A validation-v1 response includes execution_status (completed or partial) and a results.email block. Three things matter there. First is deliverability, which takes only three values: deliverable, undeliverable or undetermined. Second is checks, an object with one entry per check (syntax, the domain’s mail server, SMTP, disposable-domain catalog). Third is attributes, with descriptive data such as the inferred hosting provider or whether the address needs SMTPUTF8.

Each check has a state: completed, not_requested, not_applicable, unavailable or failed. That is the key difference from a yes/no API: an unavailable check does not mean the address is bad, it means that check could not be performed. When a reason is present it tells you why. For example, null_mx means the domain explicitly declares it does not receive mail, while a temporary DNS failure is reported as unavailable and never as “the mailbox does not exist”.

A trimmed, fictional example of an undetermined address: deliverability arrives as undetermined, checks.syntax is completed with value true, checks.mail_server is completed with value true and checks.smtp is unavailable with the reason provider_blocked. Read together, it says something precise: the address is well formed and the domain receives mail, but the provider did not let that mailbox be confirmed. With a single “status” field that information would be lost, which is the underlying reason to look at the checks and not only at the verdict.

What to do with undetermined results

There are two usual causes. One is technical and transient: a timeout, a server answering with a temporary error, or greylisting (the server deliberately rejects the first attempt and accepts the retry). The SMTP standard, RFC 5321, separates 4xx temporary replies from 5xx permanent ones, and that distinction is why you retry some and not others. The other is the destination’s configuration: a catch-all server accepts any recipient, so its acceptance does not prove the mailbox exists, and some providers block SMTP probes without giving a useful answer.

In practice, a reasonable sign-up policy is: if undeliverable, ask the user to fix the address; if undetermined, accept the sign-up and send a confirmation email, the only real proof the person controls that mailbox; if deliverable, carry on. A bulk campaign can be different: many teams prefer to leave undetermined addresses out of the first send and retry later. That decision is yours; the API gives you evidence, not the rule.

User sign-upBulk campaignvs
Same response, two policies: sign-up accepts the uncertain and confirms by email; a campaign postpones it.

Integrating without exposing the key

What this API does not do

Better said plainly. ByeBouncer does not return a global score, nor does it decide whether someone is authentic, a bot or fraud. A server accepting the recipient does not prove delivery, ownership or consent. The disposable-domain catalog only detects exact matches against known lists: no match does not guarantee the address belongs to a real person. And domain data (SPF, DMARC, age) describes the domain, not the mailbox. With those limits clear, the result is useful for filtering junk and ordering priorities, not for replacing your own judgment.

See how email verification works →

Create an account and try the API →

Read the API documentation →

Sources reviewed

Related guides