Email validation API

Email validation API for signup, CRM, and backend workflows

Validate addresses before they enter your product, campaign tools, or customer database. BounceNot returns deliverability signals through a simple JSON API and uses one credit per successful validation.

Validate a single email

Send a GET request with the email address in the path and your API key in the Authorization: Bearer header (or X-API-Key). The legacy api_key query parameter still works, but headers keep keys out of logs.

curl 'https://bouncenot.oddbench.co/api/v1/validate/support@example.com' \
  -H 'Authorization: Bearer YOUR_API_KEY'

Validate a batch

Send multiple addresses in one JSON request. Each email requires one available credit.

curl -X POST 'https://bouncenot.oddbench.co/api/v1/validate' \
  -H 'Authorization: Bearer YOUR_API_KEY' \
  -H 'Content-Type: application/json' \
  -d '{
    "emails": ["support@example.com", "sales@example.com"]
  }'

Authentication

Create an account, open private API access, and use your generated API key on server-side requests.

Credit usage

A successful validation consumes one credit. If an account has insufficient credits, the API returns a forbidden response.

Validation signals

Responses include reachability (yes, no or unknown), syntax, SMTP deliverability and catch-all, MX records, a typo suggestion, disposable, role and free-provider flags, and smtp_error (why a probe was inconclusive: greylisted, timeout, blocked…). List emails additionally carry a status and sub-status.

Example response

GET /api/v1/validate/support@example.com returns:

{
  "email": "support@example.com",
  "reachable": "yes",
  "syntax": { "valid": true, "domain": "example.com", "username": "support" },
  "smtp": {
    "host_exists": true,
    "deliverable": true,
    "full_inbox": false,
    "catch_all": false,
    "disabled": false
  },
  "smtp_error": null,
  "has_mx_records": true,
  "disposable": false,
  "role_account": true,
  "free": false,
  "suggestion": ""
}

Batch requests return {"results": [...]} with one such object per address.

Status codes

Every validated email in a list gets one status and, where there is more to say, a sub_status. They appear in the dashboard, the CSV export and the list emails API (GET /api/v1/lists/{id}/emails).

statusMeaningsub_statusMeaning
Valid
valid
The mailbox accepted our check. Safe to send. role_based A shared inbox such as info@ or sales@. It exists, but engagement is usually low and some providers treat mail to it as spam.
Invalid
invalid
Bad syntax, no mail servers, or the mailbox was refused. Will bounce; "Delete invalid" removes these. failed_syntax_check The address is not well-formed.
no_dns_entries The domain has no MX records, so nothing can receive mail for it.
possible_typo The domain looks like a misspelling of a popular provider.
mailbox_not_found The mail server said this mailbox does not exist.
mailbox_quota_exceeded The mailbox is over quota and refuses new mail.
mailbox_disabled The mail server reported the mailbox as disabled.
Catch-all
catch_all
The domain accepts any address, so the mailbox itself can't be confirmed. role_based_catch_all A role address on a domain that accepts any recipient.
Do not mail
do_not_mail
Deliverable or not, sending is a bad idea (disposable services). disposable A throwaway address from a temporary-email service.
Unknown
unknown
The mail server gave no definite answer. Not charged differently; revalidate later. greylisted The server asked us to retry later (greylisting). Revalidating usually gives a definite answer.
timeout_exceeded The mail server did not answer in time.
antispam_system An anti-spam system refused to talk to us; the mailbox could not be checked.
failed_smtp_connection The mail server refused the connection.
mail_server_temporary_error The mail server returned a temporary error.
smtp_inconclusive The mail server gave no definite answer about this mailbox.

A valid or catch-all address without a sub-status has nothing to add. Role addresses stay valid (the mailbox exists); the "Safe to send" export excludes them.

Credit balance

Poll your balance from monitoring or before a big import.

curl 'https://bouncenot.oddbench.co/api/v1/credits' \
  -H 'Authorization: Bearer YOUR_API_KEY'

# {"credits": 2500}

Usage

Validations per day, list job and API separately. Dates are UTC, inclusive, at most a year apart; the default is the last 30 days.

curl 'https://bouncenot.oddbench.co/api/v1/usage?start=2026-10-01&end=2026-10-31' \
  -H 'Authorization: Bearer YOUR_API_KEY'

# {"start": "2026-10-01", "end": "2026-10-31", "total_validations": 1240,
#  "list_validations": 1200, "api_validations": 40,
#  "days": [{"date": "2026-10-03", "list_validations": 1200, "api_validations": 0}, ...]}

API FAQ

How does API authentication work?

Each request uses an account API key generated inside BounceNot.

Does API validation use credits?

Yes. One successful API validation consumes one BounceNot credit.

What does the API return?

A JSON object per address with reachability (yes, no or unknown), syntax, SMTP deliverability, MX records, and disposable, role and free-provider flags.