// post /v1/bulk/search
Bulk Domain Search API
Discover decision-maker emails across hundreds of domains in one asynchronous API job with export-ready results.
Domains or company namesUp to 25,000 rows
curl -X POST "https://api.tomba.io/v1/bulk/search" \
-H "X-Tomba-Key: $TOMBA_API_KEY" \
-H "X-Tomba-Secret: $TOMBA_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Domain Search job","list":"piedpiper.com\nshopify.com\nnotion.so","launch":true,"webhook_url":"https://hooks.example.com/tomba"}'const res = await fetch("https://api.tomba.io/v1/bulk/search", {
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": "Domain Search job",
"list": "piedpiper.com\nshopify.com\nnotion.so",
"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/search",
headers={
"X-Tomba-Key": os.environ["TOMBA_API_KEY"],
"X-Tomba-Secret": os.environ["TOMBA_SECRET_KEY"],
},
json={
"name": "Domain Search job",
"list": "piedpiper.com\nshopify.com\nnotion.so",
"launch": True,
"webhook_url": "https://hooks.example.com/tomba"
},
)
job_id = res.json()["data"]["id"]// 01 · request
Bulk Domain Search 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
- search
- list | data | file
- Domains or company names
- launch
- true starts the job at once
- webhook_url
- Receives a signed event when the job ends
- rows
- Up to 25,000 per job
curl -X POST "https://api.tomba.io/v1/bulk/search" \
-H "X-Tomba-Key: $TOMBA_API_KEY" \
-H "X-Tomba-Secret: $TOMBA_SECRET_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Domain Search job","list":"piedpiper.com\nshopify.com\nnotion.so","launch":true,"webhook_url":"https://hooks.example.com/tomba"}'const res = await fetch("https://api.tomba.io/v1/bulk/search", {
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": "Domain Search job",
"list": "piedpiper.com\nshopify.com\nnotion.so",
"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/search",
headers={
"X-Tomba-Key": os.environ["TOMBA_API_KEY"],
"X-Tomba-Secret": os.environ["TOMBA_SECRET_KEY"],
},
json={
"name": "Domain Search job",
"list": "piedpiper.com\nshopify.com\nnotion.so",
"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
/domain-searchFielddata.organizationobject- Company name, location, social links, industry, size, revenue, description, pattern
data.organization.accept_allboolean- The domain accepts mail for any address (catch-all)
data.emails[].emailstring- Each address found
data.emails[].full_name, data.emails[].position, data.emails[].departmentstring | null- Name, job title and team
data.emails[].senioritystring | null- junior, senior or executive
data.emails[].scoreinteger- Confidence from 0 to 100
data.emails[].verification.statusstring | null- valid, accept_all, invalid or unknown, with verification.date
data.emails[].sources[]array- Where each address was found
meta.total, meta.total_pagesinteger- Addresses that match, and pages at this pageSize
meta.current, meta.pageSizeinteger- This page and its size
meta.paramsobject- The parameters the search ran with
POST /bulk/search
201 Created
{
"data": {
"id": 1042
}
}Each row, as GET /domain-search returns it
200 OK
{
"data": {
"organization": {
"website_url": "piedpiper.com",
"organization": "Pied Piper",
"location": {
"country": "US",
"city": "Palo Alto",
"state": "CA",
"street_address": "5230 Newell Road",
"postal_code": "94303"
},
"social_links": {
"twitter_url": null,
"facebook_url": null,
"instagram_url": null,
"linkedin_url": "https://www.linkedin.com/company/pied-piper",
"github_url": null,
"youtube_url": null,
"pinterest_url": null,
"tiktok_url": null
},
"disposable": false,
"webmail": false,
"phone_number": false,
"industries": "computer software",
"founded": "2014",
"company_size": "11-50",
"company_type": "privately held",
"revenue": null,
"accept_all": false,
"description": "Pied Piper builds middle-out compression for files, video and a decentralized internet.",
"pattern": "{first}",
"total_similar": 2,
"keywords": [
"compression",
"middle-out",
"decentralized internet"
],
"ranking": null,
"whois": {
"registrar_name": null,
"created_date": null,
"referral_url": null
},
"last_updated": "2025-01-15T10:32:00+01:00"
},
"emails": [
{
"email": "dinesh@piedpiper.com",
"first_name": "Dinesh",
"last_name": "Chugtai",
"full_name": "Dinesh Chugtai",
"gender": "male",
"phone_number": false,
"type": "personal",
"country": "US",
"position": "Software Engineer",
"department": "engineering",
"seniority": "senior",
"twitter": null,
"linkedin": null,
"score": 99,
"verification": {
"date": "2025-01-15T10:32:00+01:00",
"status": "valid"
},
"phone_data": [],
"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
}
]
},
{
"email": "gilfoyle@piedpiper.com",
"first_name": "Bertram",
"last_name": "Gilfoyle",
"full_name": "Bertram Gilfoyle",
"gender": "male",
"phone_number": false,
"type": "personal",
"country": "US",
"position": "Systems Architect",
"department": "engineering",
"seniority": "senior",
"twitter": null,
"linkedin": null,
"score": 97,
"verification": {
"date": "2025-01-15T10:32:00+01:00",
"status": "valid"
},
"phone_data": [],
"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
}
]
}
]
},
"meta": {
"total": 12,
"pageSize": 10,
"current": 1,
"total_pages": 2,
"params": {
"domain": "piedpiper.com",
"company": "",
"page": 1,
"limit": 10,
"department": "engineering",
"country": null,
"type": "all",
"live": false,
"enrich_mobile": false,
"webhook_url": 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
Per domain with at least one address: 1 search credit per 10 addresses returned, at most 10. Plus 5 per address 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 company domains, then launch the operation. The API searches for all email addresses associated with each domain asynchronously.
You can process up to 25,000 domains per bulk operation. Each domain returns up to 10 emails per search.
Yes, you can specify department filters (executive, marketing, HR, IT, sales, etc.) and seniority levels when creating the bulk operation.
Each domain returns found email addresses with full name, position, department, seniority, LinkedIn profile, confidence score, and sources.
Processing time depends on the number of domains. Typical processing is 2-5 seconds per domain. A batch of 25,000 domains typically completes within 1-2 hours.
Each domain search that returns results is counted as 1 request for up to 10 emails. Domains with no results found are not counted.
Yes, configure a webhook URL to receive a notification when your bulk domain search completes with the bulk_id and status.
Once processing completes, use the download endpoint to get all results as CSV or JSON, including all emails found for each domain.
Yes. You can run returned emails through Bulk Email Enrichment or Bulk Email Verifier to add context and improve deliverability before outreach.
Business domains with active websites and public employee footprints usually produce stronger coverage. Use root domains and remove duplicates before submission.