All articles
Developer5 September 20269 min read

Email Verification API: What to Look for and How to Choose (2026)

If you're evaluating email verification APIs, you'll find that most services describe themselves in almost identical terms: "real-time verification," "99% accuracy," "SMTP check included." The marketing copy doesn't help you compare. The API response does.

This guide focuses on what actually matters when choosing and integrating an email verification API: what the checks cover, which fields to rely on, how to interpret edge cases, and what to watch out for.

What the API actually checks

A complete email verification sequence has three distinct layers:

Layer 1: Syntax validation

The API confirms the address is structurally valid — an @ symbol, a local part, a domain. This happens instantly and costs nothing to compute. It's a prerequisite, not a feature. If a provider counts this as a "check," that's a red flag.

Layer 2: DNS / MX record lookup

The API queries the domain's DNS records to confirm it has Mail Exchange (MX) records configured. MX records tell the world which mail servers accept email for a domain. If there are no MX records, no email can be delivered — the domain isn't set up to receive mail.

This catches domains that exist but have no email infrastructure: company.com might resolve to a website but have no MX records, making every @company.com address undeliverable.

Layer 3: SMTP handshake

This is the check that separates useful APIs from basic format validators. The API connects to the domain's mail server (using the MX records found in Layer 2) and simulates delivering an email to the specific address. It performs the SMTP handshake up to the RCPT TO command — the point where the server either accepts or rejects the address.

If the server says the address doesn't exist, the API returns invalid. If it accepts, the address is likely deliverable.

No real email is sent. The connection is dropped after the check. No trace is left in the recipient's inbox.

Response fields that matter

A well-structured API response includes more than just a pass/fail. Here's what a complete response looks like and what each field means:

{
  "email": "user@example.com",
  "status": "valid",
  "sub_status": null,
  "domain": "example.com",
  "mx_found": true,
  "smtp_check": true,
  "is_disposable": false,
  "is_role_based": false,
  "is_catch_all": false
}

status is your primary decision field. The three values you'll encounter:

| Status | Meaning | Action | |---|---|---| | valid | Address exists and is deliverable | Accept | | invalid | Address does not exist | Reject | | unknown | Server couldn't confirm (catch-all, timeout, block) | Context-dependent |

is_disposable flags temporary inbox services — Mailinator, Guerrilla Mail, and thousands of domain-specific providers. An address can return valid SMTP-wise (the mailbox exists right now) while still being disposable. You need both checks.

is_catch_all indicates the domain's mail server accepts every address regardless of whether the specific mailbox exists. This makes SMTP verification inconclusive for that domain — which is why catch-all addresses return unknown status rather than valid.

is_role_based identifies shared inboxes: info@, admin@, support@, team@. These pass all technical checks but are typically monitored by multiple people, rarely engaged with personally, and frequently cause deliverability issues with commercial email.

mx_found and smtp_check give you granularity on exactly where a failure occurred — useful for logging and debugging.

The catch-all problem

Catch-all domains are the hardest part of email verification, and every API handles them differently.

When a domain is configured as catch-all, its mail server responds "yes, I'll accept that" to every address during the SMTP check — even addresses that don't exist. This means there's no way to confirm whether a specific address at that domain is real.

Good APIs return unknown for catch-all addresses and set is_catch_all: true. Bad APIs return valid — technically accurate from the SMTP perspective, but misleading in practice.

For catch-all domains, you have two options:

  1. Accept and monitor — send one email and suppress on first bounce
  2. Apply a secondary heuristic — if you see that 80% of addresses from a domain return catch-all, the domain itself might be suspicious

Speed and what affects it

SMTP verification involves a real network round-trip to a remote mail server. The time this takes depends on:

  • The mail server's geographic location and response time
  • Whether the server applies rate limiting or greylisting
  • Whether your API provider's infrastructure is geographically close to the target mail server

Typical response times range from 500ms to 3 seconds for a single check. Some mail servers deliberately delay responses (tarpitting) to slow down spam — these can push individual checks to 8–10 seconds.

What this means for your integration: don't put email verification on a 2-second timeout. Use 8–10 seconds for individual checks. If the check times out, treat the result as unknown and fail open.

// Don't do this
const result = await verifyEmail(email); // default 5s timeout — too short

// Do this
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), 10_000);

try {
  const result = await verifyEmail(email, { signal: controller.signal });
  // handle result
} catch (err) {
  if (err.name === "AbortError") {
    // Timeout — fail open, don't block the signup
  }
} finally {
  clearTimeout(timer);
}

Accuracy: what "99%" actually means

Most email verification providers claim 99% accuracy. This number is essentially meaningless without context.

What does accuracy mean for a verification API? It means: of addresses that were checked, what percentage of the "valid" verdicts were actually deliverable, and what percentage of the "invalid" verdicts were actually undeliverable?

False positives (returned valid, actually bounced) are the more expensive error — you send to an address, get a bounce, and take the deliverability hit. False negatives (returned invalid, was actually deliverable) cost you a missed user.

The honest answer is that no provider can claim a fixed accuracy number because:

  • Mail server behavior changes (an address might be valid today and deleted tomorrow)
  • Catch-all domains introduce inherent uncertainty
  • Some servers deliberately block verification checks

A good API minimizes false positives by being conservative — returning unknown when uncertain, rather than guessing valid. That's the right tradeoff.

Questions to ask before you integrate

Is the SMTP check actually performed, or just MX lookup? Some providers advertise "SMTP verification" but only perform DNS checks. Look for smtp_check in the response or ask explicitly. MX lookup alone misses all invalid addresses on domains that have mail infrastructure.

How are catch-all domains handled? The answer should be: returned as unknown with an is_catch_all flag. If the provider returns catch-all addresses as valid, that's inflating their accuracy numbers at your expense.

What's the rate limit and how is it enforced? Understand whether the limit is per-second, per-minute, or per-day, and what happens when you exceed it — hard error, soft queue, or silent drop. For signup forms at scale, per-second limits matter more than daily caps.

Is there a bulk verification option? For existing lists, per-API-call verification is inefficient and expensive. A good provider offers batch/bulk processing where you upload a CSV and get results back in bulk, at a lower per-address cost.

What does the pricing model look like? Credits-based pricing (pay per verification) is more economical for variable-volume use cases than monthly plans with fixed caps. If you run a campaign twice a year, you don't want to pay for 50,000 verifications per month.

Is there a free tier to test with? You should be able to run 50–100 real checks against a live API before committing. Any provider that requires payment to evaluate is making integration harder for no good reason.

A note on verification at signup vs. bulk verification

These are different use cases with different requirements:

Real-time / signup verification — one address at a time, sub-10-second response expected, runs during user interaction. Prioritizes speed and reliability. Fail open when the API is unavailable.

Bulk verification — thousands to millions of addresses, asynchronous processing, results delivered via webhook or download. Prioritizes throughput and cost-per-check. Use before campaigns, not during live flows.

Some applications need both: real-time at signup to keep the list clean as it grows, and bulk verification quarterly to re-check addresses that may have been abandoned since signup.

What good integration looks like

// The complete pattern
async function checkEmailAtSignup(email: string): Promise<{
  allowed: boolean;
  reason?: string;
}> {
  // 1. Format check — fast, free, no API call
  if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
    return { allowed: false, reason: "Invalid email format." };
  }

  // 2. API verification
  let result;
  try {
    result = await verifyEmail(email); // your API call with 10s timeout
  } catch {
    return { allowed: true }; // fail open on API error
  }

  // 3. Apply policy
  if (result.status === "invalid") {
    return { allowed: false, reason: "That email address doesn't exist." };
  }

  if (result.is_disposable) {
    return { allowed: false, reason: "Temporary email addresses are not accepted." };
  }

  // Accept valid and unknown (catch-all, timeout) addresses
  return { allowed: true };
}

The pattern: reject invalid firmly, reject disposable firmly, accept everything else (including unknown) rather than blocking potentially legitimate users.

Getting started with StopBouncing

The StopBouncing API performs all three verification layers — syntax, MX, and live SMTP — plus disposable and catch-all detection in a single call. Response time is typically under 2 seconds for most domains.

New accounts start with 100 free verifications. No credit card required to test the integration. Credits are purchased as needed and never expire — so there's no pressure to use them before a billing cycle resets.

View the API reference for the complete request and response schema. → Create an account to get your API key.

Ready to clean your email list?

Verify thousands of addresses in minutes. No subscription — pay only for what you use.