Email verification in Postman
Postman is where most people meet an API before they write a line against it. Two environments, one collection-level auth setting, and you can exercise every endpoint without touching your codebase.
The setup worth copying is the pair of environments. A sandbox environment pointed at a zb_test_ key lets you hammer the collection with no credits spent and no SMTP connections opened, which makes it safe to leave in a scheduled monitor.
Collection-level Bearer auth reading {{api_key}}, with environments swapping the key between live and sandbox.
Verify one address
You branch on four results: valid, invalid, catch_all and unknown. Role and disposable are boolean flags beside the result, so test them separately. Unknown is the branch most code forgets, and it is never billed.
// Environment: "ZapBounce — sandbox"
{
"base_url": "https://api.zapbounce.com/v1",
"api_key": "zb_test_...", // set type: secret, not default
"sample_email": "unknown@sandbox.zapbounce.com"
}
// Environment: "ZapBounce — live"
{
"base_url": "https://api.zapbounce.com/v1",
"api_key": "zb_live_...",
"sample_email": "ada@example.com"
}
// Collection → Authorization → Bearer Token → {{api_key}}
// Every request inherits it. Nothing hardcodes a key into a saved request,
// which is what leaks when someone exports the collection to a colleague.
// POST {{base_url}}/verify
{
"email": "{{sample_email}}"
}Verify a list
Submit a batch rather than looping the single endpoint. We pace probes per receiving mail host, which protects the sending reputation your results depend on.
// Request 1 — POST {{base_url}}/batches
// Tests tab: capture the batch id for the next request in the chain.
const body = pm.response.json();
pm.test("batch accepted", () => {
pm.response.to.have.status(200);
pm.expect(body.batch_id).to.be.a("string");
});
// Deduplication is visible here: unique is lower than submitted on a real list.
pm.test("duplicates collapsed before billing", () => {
pm.expect(body.unique).to.be.at.most(body.submitted);
});
pm.collectionVariables.set("batch_id", body.batch_id);
// Request 2 — GET {{base_url}}/batches/{{batch_id}}
// Pre-request: pause between polls without a fixed sleep in the runner.
setTimeout(() => {}, 5000);
// Tests: loop back to this request until the batch finishes.
const status = pm.response.json();
if (status.status !== "complete") {
pm.execution.setNextRequest("Get batch status"); // poll again
} else {
pm.test("coverage reported next to the verdicts", () => {
pm.expect(status).to.have.property("coverage");
pm.expect(status.summary).to.have.property("unknown");
});
pm.collectionVariables.set("results_url", status.results_url);
}Errors and retries
A 429 and a 5xx are worth retrying. A 402 for credits and a 400 for a malformed address will fail the same way on every attempt, so stop.
// Tests tab on POST {{base_url}}/verify.
// The assertion that matters is the last one: unknown must never be billed.
const r = pm.response.json();
pm.test("responds in under 10 seconds", () => {
pm.expect(pm.response.responseTime).to.be.below(10000);
});
pm.test("result is one of the four", () => {
pm.expect(r.result).to.be.oneOf(["valid", "invalid", "catch_all", "unknown"]);
});
pm.test("role and disposable are boolean flags, not results", () => {
pm.expect(r.role).to.be.a("boolean");
pm.expect(r.disposable).to.be.a("boolean");
});
pm.test("unknown results are never billed", () => {
if (r.result === "unknown") pm.expect(r.billed).to.equal(false);
});
// Error path: point the collection at an empty sandbox key and run this.
pm.test("errors carry a request id", () => {
if (pm.response.code >= 400) {
const { error } = pm.response.json();
pm.expect(error).to.have.property("code");
pm.expect(error).to.have.property("request_id"); // quote it in support
}
});
// 429 handling in the runner: back off rather than hammering through the run.
if (pm.response.code === 429) {
const wait = Number(pm.response.headers.get("Retry-After") ?? 5) * 1000;
setTimeout(() => {}, wait);
pm.execution.setNextRequest(pm.info.requestName);
}Postman: common questions
Is there a published collection?
The requests on this page are the whole surface: verify, batches, batch status, results, files, credits, account. Build them once and the collection is done.
Can I run it as a monitor?
Yes, and use the sandbox key. A monitor on a live key spends credits on a schedule forever.
How do I test the unknown branch?
unknown@sandbox.zapbounce.com with a test key returns it on demand, which is the only reliable way to exercise that path.
Run this Postman code today
100 free checks a month, no card, credits that never expire, and unknown results that cost nothing.