Verification for the engineer wiring it up

Developers get handed this ticket with a sentence of context: stop bad emails getting into the database. The interesting decisions are all in what happens after the API answers.

What follows is the design detail that matters when you are the one holding the pager, rather than a feature list.

The branch nobody writes is the one that fires at 2am

Four results come back, plus three boolean flags, and most integrations handle two of the results. Valid goes forward, invalid gets rejected, and catch-all and unknown fall into an else that was written in a hurry, along with every flag nobody read.

Unknown is the one that hurts. It means a receiving server refused to answer, which happens when Microsoft-hosted domains throttle or when greylisting kicks in, and it almost never fires in local testing. Then a batch runs on a Tuesday when one large host is being difficult and a few thousand real customers land in whatever your else branch does.

That is why there is a reserved sandbox address that returns unknown on demand, and why the result field is a string rather than a boolean. A boolean would have made your integration shorter and your incident longer.

How the work gets done

The order that matters for developers, rather than a generic checklist.

  1. Model the result as a closed set

    Four values on the result field: valid, invalid, catch_all, unknown. Role, disposable and free_provider arrive as separate booleans, so read them on their own and never as a fifth case. In TypeScript or Rust, an exhaustive match on the four means a missed branch becomes a compile error rather than a silent fallthrough.

  2. Fail open at the signup path

    A two-second timeout, and a timeout counts as a pass. A verifier having a slow second should never cost you a registration, and that decision is easier to make now than during the incident.

  3. Use webhooks, not a polling loop

    The batch endpoint returns immediately and posts a signed event when it finishes. Verify the HMAC against the raw bytes before parsing, because re-serialising the body is the reason most signature checks fail.

  4. Point CI at a sandbox key

    Scripted verdicts, no SMTP connections, no credits. There is a deliberately slow address for testing your client timeout and a rate-limited one for testing backoff.

What verification will not do here

What it costs

A hundred free credits a month, no card, is enough to develop against. Sandbox calls are unlimited and cost nothing at all. Production starts at $5 for a thousand addresses.

Every tier works the same way. Unknown results and duplicates are never billed, and credits do not expire.

Questions we get asked

Is there an SDK?

No, and one would wrap four HTTP calls in a dependency you would then have to keep pinned. Every language page carries a working client in that language's own idiom.

How do I test the unknown branch?

unknown@sandbox.zapbounce.com with a test key. It is the only reliable way to hit a path that otherwise fires when a mail host is having a bad day.

Does verification send an email?

No. The connection closes before DATA, so nothing is delivered to the address being checked.

What happens to my credits on an error?

Nothing. A credit is spent only on a valid, invalid or catch-all result. Errors, rate limits, duplicates, sandbox calls and unknown results never cost one.

Try it on your own list first

100 free checks a month, no card. Run a sample and read the unresolved count before you decide anything.