Migrate from Emailable
This guide maps the Emailable API v1 (single verification, batch verification, and account info) to the Tomba Email Verifier and bulk verifier jobs. Emailable API behavior checked on 2026-09-30 against the Emailable API reference.
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, so there is no
249response to retry.
Endpoint mapping
Replace the base URL https://api.emailable.com/v1 with https://api.tomba.io/v1.
| Emailable | Tomba |
|---|---|
GET /v1/verify (or POST) | GET /v1/email-verifier |
POST /v1/batch | POST /v1/bulk/verifier, then PUT /v1/bulk/verifier/{id} to launch |
GET /v1/batch?id= | GET /v1/bulk/verifier/{id}/progress, then GET /v1/bulk/verifier/{id}/download |
GET /v1/account | GET /v1/me |
Authentication changes
Emailable reads the key from the api_key parameter (or an OAuth access_token), or from an Authorization: Bearer header. Tomba needs two headers, X-Tomba-Key and X-Tomba-Secret, and doesn't accept credentials in the query string or body:
Code
If you call Emailable from browser code with a public API key, move the call to your server and keep the Tomba key and secret there (Security). Tomba API keys expire; plan their rotation with Key expiry.
Parameter mapping
| Emailable | Tomba | Notes |
|---|---|---|
api_key, access_token | X-Tomba-Key and X-Tomba-Secret headers | |
email | email | Required. A malformed address returns 422 params_invalid instead of a result. |
smtp | No equivalent | |
accept_all | No equivalent | Every Tomba response includes data.email.accept_all. |
timeout | No equivalent | Set the timeout in your HTTP client. |
captcha_response | No equivalent | |
Batch emails | list | A newline-separated string, instead of a comma-separated string or JSON array. Also send name. |
Batch url | webhook_url | Receives a signed event when the job ends. See Bulk job events. |
Batch response_fields, retries, simulate | No equivalent | |
Batch status id | {id} in the path | |
Batch status partial | No equivalent | Results are available only as a CSV download once the job is completed. |
Response field mapping
Emailable returns a flat object. Tomba nests the checks in data.email and lists the public pages where the address appears in data.sources. Field definitions are in Email verifier response.
| Emailable | Tomba | Notes |
|---|---|---|
email | data.email.email | An empty string when the domain is disposable. |
state | data.email.status, data.email.result | See Status mapping. |
reason | No equivalent | Tomba reports greylisted, block, and mx_check as separate fields. |
score | data.email.score | Computed differently. |
accept_all | data.email.accept_all | |
disposable | data.email.disposable | |
free | data.email.webmail | |
mx_record | data.email.mx.records | An array of MX host names instead of one string. |
smtp_provider | data.email.smtp_provider | |
role, no_reply, mailbox_full | No equivalent | |
did_you_mean | No equivalent | |
user, domain, tag | No equivalent | Split the address yourself. |
first_name, last_name, full_name, gender, birth_year | No equivalent | |
duration | No equivalent | |
message | errors.message | Returned with an HTTP error status; see Error mapping. |
Tomba also returns block, greylisted, gibberish, regex, and whois, which have no Emailable counterpart. Read your remaining balance, Emailable's available_credits, from the X-Verify-Remaining header or GET /v1/me; see Check usage.
Status mapping
Emailable state | Tomba status | Tomba result |
|---|---|---|
deliverable | valid | deliverable |
undeliverable | invalid | undeliverable |
risky | accept_all for a catch-all domain; disposable for a disposable domain | risky; an empty string for disposable |
unknown | unknown | risky |
An address that Emailable returns as undeliverable with the reason invalid_email fails syntax checks; Tomba rejects it with 422 params_invalid instead of returning a status.
Tomba's result uses the same words as Emailable's state for deliverable, undeliverable, and risky, but an inconclusive check is risky, not unknown. Branch on status to tell them apart, and compare it case-insensitively. Each value is defined in Status values.
Error mapping
Both APIs signal failures with HTTP status codes. Emailable's error body is {"message": "…"}; Tomba's is an errors object with type, message, and code.
| Emailable | Tomba | What to do |
|---|---|---|
249 Try Again | Not returned | Remove the retry loop. |
400 Bad Request | 422 params_invalid | Fix the parameter named in the message. |
401 no API key | 400 authentication_failed | Send both headers. |
403 invalid API key | 401 authentication_failed (wrong key or secret), 400 api_key_expired | Check both headers; rotate an expired key. |
402 Payment Required | 402 quota_exceeded | Wait for your usage window to renew or add credits. |
404 batch not found | GET /v1/bulk/verifier/{id} returns 404 unknown_record | Check the job ID. |
429 Too Many Requests | 429 rate_limit | Retry after the Retry-After delay; see Handle 429 responses. |
500, 503 | 500 api_error | Retry with backoff. |
| 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. |
Error responses don't consume credits. Every type is listed in Errors.
Bulk and async jobs
| Emailable | Tomba |
|---|---|
POST /v1/batch with emails | POST /v1/bulk/verifier with name and a newline-separated list, or a CSV file |
| Verification starts on creation | Launch the job: PUT /v1/bulk/verifier/{id} |
Poll GET /v1/batch for processed and total | Poll GET /v1/bulk/verifier/{id}/progress for status and progress until status is completed |
The url callback | webhook_url. See Bulk job events. |
emails array (up to 1,000 addresses) or a download_file ZIP | GET /v1/bulk/verifier/{id}/download?file=full returns a CSV for every job size |
total_counts, reason_counts | No equivalent. Count the rows of the CSV. |
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/verify and returns Emailable's field names for the values Tomba supplies. It needs Node.js 18 or later.
Code
Cutover checklist
- Store the Tomba key and secret as
TOMBA_API_KEYandTOMBA_SECRET_KEY, send them asX-Tomba-KeyandX-Tomba-Secret, and removeapi_keyand bearer tokens from your requests and logs. - Point single verifications at
GET https://api.tomba.io/v1/email-verifier, dropsmtp,accept_all, andtimeout, and set a client timeout of at least 180 seconds. - Remove the
249retry loop and swap error handling:400for a missing key,401for a wrong one,422for bad parameters, and408and451as new cases. - Translate
statewith the status mapping, branching onstatusrather thanresult, and compare it case-insensitively. - Replace batches with
verifierbulk jobs: create withlistorfile, launch, receive thewebhook_urlevent instead of theurlcallback, and download the CSV. - Verify the same sample list with both services and compare the mapped results before you switch production traffic.