Migrate from Bouncer
This guide maps the Bouncer API v1.1 (real-time verification, batch verification, and credits) to the Tomba Email Verifier and bulk verifier jobs. Bouncer API behavior checked on 2026-09-29 against the Bouncer API documentation.
Before you begin
- Get your API key (
ta_…) and secret (ts_…); see Authentication. - Check what a verification costs in Credit costs and your plan's throttling in Limits by plan.
- Set your HTTP client timeout to at least 180 seconds. Tomba returns the finished result in the response.
Endpoint mapping
Replace the host api.usebouncer.com with api.tomba.io.
| Bouncer | Tomba |
|---|---|
GET /v1.1/email/verify | GET /v1/email-verifier |
POST /v1.1/email/verify/batch | POST /v1/bulk/verifier, then PUT /v1/bulk/verifier/{id} to launch |
GET /v1.1/email/verify/batch/{batchId} | GET /v1/bulk/verifier/{id}/progress |
GET /v1.1/email/verify/batch/{batchId}/download | GET /v1/bulk/verifier/{id}/download |
POST /v1.1/email/verify/batch/{batchId}/finish | No equivalent |
DELETE /v1.1/email/verify/batch/{batchId} | DELETE /v1/bulk/verifier/{id}/delete |
POST /v1.1/email/verify/batch/sync | No equivalent. Use a bulk job, or send single requests. |
GET /v1.1/credits | GET /v1/me |
Authentication changes
Bouncer reads the key from the x-api-key header or from basic authentication. Tomba needs two headers, X-Tomba-Key and X-Tomba-Secret:
Code
Tomba API keys expire; plan their rotation with Key expiry.
Parameter mapping
| Bouncer | Tomba | Notes |
|---|---|---|
email | email | Required. A malformed address returns 422 params_invalid instead of a result. |
timeout | No equivalent | Set the timeout in your HTTP client. |
Batch body [{"email": …}] | list | A string with one address per line. |
Batch callback | No equivalent | Poll the job's progress. |
Batch skip-header | No equivalent | Tomba always treats the first row of a CSV file as a header. |
Status with-stats | No equivalent | |
Download download=all | file=full | |
Download download=deliverable | file=valid | |
Download download risky, undeliverable, unknown | No equivalent | Download file=full and filter the rows. |
Response field mapping
Bouncer returns a flat object whose flags are the strings yes, no, and unknown. Tomba nests the checks in data.email, uses booleans, and lists the public pages where the address appears in data.sources. Field definitions are in Email verifier response.
| Bouncer | Tomba | Notes |
|---|---|---|
email | data.email.email | An empty string when the domain is disposable. |
status | data.email.result, data.email.status | See Status mapping. |
reason | data.email.status and the booleans in data.email | See Status mapping. |
domain.acceptAll | data.email.accept_all | |
domain.disposable | data.email.disposable | |
domain.free | data.email.webmail | |
domain.name | No equivalent | Split data.email.email at @. |
account.role, account.disabled, account.fullMailbox | No equivalent | |
dns.type, dns.record | data.email.mx_check, data.email.mx.records | |
provider | data.email.smtp_provider | |
score | data.email.score | Computed differently. Recalibrate any threshold you apply to it. |
toxic, toxicity | No equivalent | |
retryAfter | No equivalent | data.email.greylisted is true when the mail server deferred the check. |
didYouMean | No equivalent |
Tomba also returns block, gibberish, regex, and whois, which have no Bouncer counterpart.
Status mapping
Bouncer status | Tomba status | Tomba result |
|---|---|---|
deliverable | valid | deliverable |
risky, reason low_deliverability | accept_all | risky |
risky, reason low_quality | disposable | Empty string |
undeliverable | invalid | undeliverable |
unknown | unknown | risky |
Bouncer reason | Tomba |
|---|---|
accepted_email | status is valid |
rejected_email | status is invalid |
invalid_email | The request fails with 422 params_invalid |
invalid_domain | mx_check is false |
low_deliverability | status is accept_all for a catch-all domain. A full mailbox has no equivalent. |
low_quality | status is disposable for a disposable domain |
dns_error, unavailable_smtp, unsupported, timeout, unknown | No equivalent reason. An inconclusive check returns status unknown; a failed check returns 408 proxy_error. |
Branch on status rather than result: Tomba's unknown status carries the result risky, and a disposable address has an empty result. Compare status case-insensitively. Each value is defined in Status values.
Error mapping
| Bouncer | Tomba | What to do |
|---|---|---|
400 | 422 params_invalid | Fix the parameter named in the message. |
401 user not found | 400 authentication_failed (missing or malformed), 400 api_key_expired, 401 authentication_failed (wrong key or secret) | Check both headers; rotate an expired key. |
402 Payment Required | 402 quota_exceeded | Wait for your usage window to renew or add credits. |
429 | 429 rate_limit | Retry after the Retry-After delay; see Handle 429 responses. |
503 | 500 api_error or 504 | Retry with backoff. |
404 batch not found | 404 unknown_record | Check the job ID. |
405 batch not completed | 404 | Download only after /progress reports completed. |
| No equivalent | 408 proxy_error | The mailbox check failed. Retry later. |
| No equivalent | 451 claimed_email | The owner of the address asked Tomba to stop processing it. Remove it from your list. |
Bouncer's error body has status, error, and message; Tomba's errors object has type, message, and code. Error responses don't consume credits. Every type is listed in Errors.
Bulk and async jobs
| Bouncer | Tomba |
|---|---|
POST /v1.1/email/verify/batch with a JSON array or a text file | POST /v1/bulk/verifier with name and a newline-separated list, or a CSV file |
| The batch is queued on creation | Launch it: PUT /v1/bulk/verifier/{id} |
Poll the batch status, or pass callback | Poll GET /v1/bulk/verifier/{id}/progress until status is completed, or pass webhook_url to receive an event. |
Download JSON, or CSV with Accept: text/csv | GET /v1/bulk/verifier/{id}/download returns CSV only |
Code
The launch, progress, and download requests are shown in Lifecycle. Row limits and daily job limits are in Limits, and a job is charged when you first download its results; see Billing.
Code example
This function replaces a call to /v1.1/email/verify and returns Bouncer's field names, with yes and no flags. It needs Node.js 18 or later.
Code
Cutover checklist
- Store the Tomba key and secret as
TOMBA_API_KEYandTOMBA_SECRET_KEY, and send them asX-Tomba-KeyandX-Tomba-Secretinstead ofx-api-key. - Point single verifications at
GET https://api.tomba.io/v1/email-verifier, droptimeout, and set a client timeout of at least 180 seconds. - Read results from
data.email, convertyes/noflag checks to booleans, and translatestatusandreasonwith the status mapping. - Handle
402and429as before, add451and408, and treat an emptydataarray as an unknown job. - Replace batches with
verifierbulk jobs: create, launch, poll/progressinstead of usingcallback, and download the CSV. - Verify the same sample list with both services and compare the mapped results before you switch production traffic.