// post /v1/bulk/verifier
Bulk Email Verifier API
Clean and score high-volume email lists with one asynchronous verification pipeline built for senders at scale.
Email addressesUp to 20,000 rows
curl -X POST "https://api.tomba.io/v1/bulk/verifier" \
-H "X-Tomba-Key: $TOMBA_API_KEY" \
-H "X-Tomba-Secret: $TOMBA_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Email Verifier job","list":"richard@piedpiper.com\njohn@example.com","launch":true,"webhook_url":"https://hooks.example.com/tomba"}'const res = await fetch("https://api.tomba.io/v1/bulk/verifier", {
method: "POST",
headers: {
"X-Tomba-Key": process.env.TOMBA_API_KEY,
"X-Tomba-Secret": process.env.TOMBA_SECRET_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({
"name": "Email Verifier job",
"list": "richard@piedpiper.com\njohn@example.com",
"launch": true,
"webhook_url": "https://hooks.example.com/tomba"
})
});
const { data } = await res.json(); // { id }import os, requests
res = requests.post(
"https://api.tomba.io/v1/bulk/verifier",
headers={
"X-Tomba-Key": os.environ["TOMBA_API_KEY"],
"X-Tomba-Secret": os.environ["TOMBA_SECRET_KEY"],
},
json={
"name": "Email Verifier job",
"list": "richard@piedpiper.com\njohn@example.com",
"launch": True,
"webhook_url": "https://hooks.example.com/tomba"
},
)
job_id = res.json()["data"]["id"]// 01 · request
Bulk Email Verifier is one HTTPS request
Send the parameters with your key and secret. Every SDK, the CLI and the MCP server make this same call.
- type
- verifier
- list | data | file
- Email addresses
- launch
- true starts the job at once
- webhook_url
- Receives a signed event when the job ends
- rows
- Up to 20,000 per job
curl -X POST "https://api.tomba.io/v1/bulk/verifier" \
-H "X-Tomba-Key: $TOMBA_API_KEY" \
-H "X-Tomba-Secret: $TOMBA_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Email Verifier job","list":"richard@piedpiper.com\njohn@example.com","launch":true,"webhook_url":"https://hooks.example.com/tomba"}'const res = await fetch("https://api.tomba.io/v1/bulk/verifier", {
method: "POST",
headers: {
"X-Tomba-Key": process.env.TOMBA_API_KEY,
"X-Tomba-Secret": process.env.TOMBA_SECRET_KEY,
"Content-Type": "application/json"
},
body: JSON.stringify({
"name": "Email Verifier job",
"list": "richard@piedpiper.com\njohn@example.com",
"launch": true,
"webhook_url": "https://hooks.example.com/tomba"
})
});
const { data } = await res.json(); // { id }import os, requests
res = requests.post(
"https://api.tomba.io/v1/bulk/verifier",
headers={
"X-Tomba-Key": os.environ["TOMBA_API_KEY"],
"X-Tomba-Secret": os.environ["TOMBA_SECRET_KEY"],
},
json={
"name": "Email Verifier job",
"list": "richard@piedpiper.com\njohn@example.com",
"launch": True,
"webhook_url": "https://hooks.example.com/tomba"
},
)
job_id = res.json()["data"]["id"]// 02 · response
What comes back
JSON, the same in every language. Fields Tomba doesn't know are null, never guessed.
GET
/email-verifierFielddata.email.resultstring- deliverable, risky or undeliverable; empty for a disposable domain
data.email.statusstring- valid, accept_all, invalid, unknown or disposable (compare case-insensitively: a live check can return Valid)
data.email.scoreinteger- Confidence: 99 for valid, 77 or more for accept_all, 2 for disposable
data.email.smtp_providerstring | null- Mail provider from the MX records, such as Google
data.email.mx.recordsarray | null- The domain's MX hosts
data.email.mx_check, data.email.smtp_checkboolean- The domain has MX records (smtp_check is the same check; status says whether the mailbox exists)
data.email.accept_all, data.email.greylisted, data.email.blockboolean- Catch-all domain, check deferred, check refused by the server
data.email.disposable, data.email.webmail, data.email.gibberish, data.email.regexboolean- Disposable or webmail domain, random-looking address, valid syntax
data.sources[]array- Where the address was found
data.phone_data[]array | null- Phone numbers, when you send enrich_mobile
POST /bulk/verifier
201 Created
{
"data": {
"id": 1042
}
}Each row, as GET /email-verifier returns it
200 OK
{
"data": {
"email": {
"email": "richard@piedpiper.com",
"result": "deliverable",
"status": "valid",
"score": 99,
"smtp_provider": "Google",
"mx": {
"records": [
"aspmx.l.google.com",
"alt1.aspmx.l.google.com"
]
},
"mx_check": true,
"smtp_server": true,
"smtp_check": true,
"accept_all": false,
"greylisted": false,
"block": false,
"gibberish": false,
"disposable": false,
"webmail": false,
"regex": true,
"whois": {
"registrar_name": null,
"referral_url": null,
"created_date": null
}
},
"sources": [
{
"uri": "https://piedpiper.com/blog/engineering",
"website_url": "piedpiper.com",
"extracted_on": "2024-06-01T09:14:07+01:00",
"last_seen_on": "2025-01-10T17:02:44+01:00",
"still_on_page": true
}
],
"phone_data": null
}
}// 03 · cost and limits
What a call costs
A call is charged only under the condition below. Rate limits depend on your plan.
// cost
1 verification credit per row, except disposable addresses. Plus 5 search credits per row with phone data.
Charged once, at the first download; later downloads are free
- Jobs created: 15 per day for each type
- Running jobs: 2 per type
- Downloads: 25 per day for each job
- Request size: 4 MB (CSV, list or rows)
Create a bulk operation by uploading a list of email addresses, then launch the operation. The API verifies all emails asynchronously using multi-layer checks. Use webhooks or polling to monitor progress.
You can verify up to 20,000 email addresses per bulk operation. For larger lists, create multiple bulk operations.
Each email undergoes syntax validation, MX record checks, SMTP verification, disposable detection, catch-all detection, and deliverability scoring.
If an address Tomba returned as valid hard-bounces, the credit comes back under the data-quality guarantee (verifier result deliverable or finder score of 60 or more, sent within 30 days from a domain with SPF, DKIM and DMARC).
Speed depends on the list size and on how fast each mail server answers. Poll the job or set a webhook to hear when it finishes.
Each result includes the email, verification status (valid, invalid, accept_all, unknown), confidence score, disposable flag, SMTP provider, and MX records.
Once processing completes, use the download endpoint to get results as CSV or JSON. Results include all verification data for each email.
Yes, configure a webhook URL to receive notifications when your bulk verification completes or when errors occur during processing.
Accept-all domains can be valid but riskier. Prioritize higher confidence scores and consider segmented sending strategies for these records.
Verify lists close to send time, suppress invalid and disposable addresses, and re-verify older lists periodically to maintain deliverability.