Bulk Operations API
Domain Search Bulk Overview
Bulks Domain Search allows you to process thousands of domains simultaneously to discover email addresses, gather domain intelligence, and build comprehensive prospect lists. This powerful feature enables sales and marketing teams to scale their outreach efforts efficiently.
Key Features
Mass Domain Processing : Search up to 15,000 domains in a single bulk operation
Email Discovery : Find email addresses associated with each domain
Email Type Filtering : Filter results by personal, generic, or department-specific emails
Department Targeting : Focus on specific departments (sales, marketing, engineering, etc.)
Result Limits : Configure maximum emails per domain (1-100)
Verification Integration : Optional email verification for higher deliverability
Export Options : Download results in CSV format with multiple file types
Progress Tracking : Real-time monitoring of bulk processing status
How Domain Search Bulk Works
Upload Domain List : Provide domains via text input or CSV file upload
Configure Parameters : Set email type filters, department preferences, and result limits
Launch Processing : Initiate the bulk search operation
Monitor Progress : Track completion status in real-time
Download Results : Export discovered emails in various formats (full, valid only, not found)
Limitations
Each Bulk is limited to 15,000 domains
Additional rows will be skipped
Some special or unexpected characters may be deleted in the file
Invalid websites won't be imported
Duplicate URLs won't be imported
For better results, we use the domain name instead of the company name
Go SDK Integration
Installation
go get github.com/tomba-io/go
Basic Domain Search
package main
import (
" fmt "
" log "
" strings "
" time "
" github.com/tomba-io/go/tomba "
" github.com/tomba-io/go/tomba/models "
)
func main () {
// Initialize Tomba client
client := tomba. NewClient ( "YOUR_TOMBA_KEY" , "YOUR_TOMBA_SECRET" )
// Basic domain search
params := & models . BulkSearchCreateParams {
BulkCreateParams: models . BulkCreateParams {
Name: "SaaS Companies Email Search" ,
List: "stripe.com \n shopify.com \n zoom.us \n slack.com \n dropbox.com" ,
Sources: true ,
Verify: true ,
},
BulkSearchParams: models . BulkSearchParams {
Maximum: "20" , // Find up to 20 emails per domain
},
}
// Create the bulk search
response, err := client. CreateSearchBulk (params)
if err != nil {
log. Fatal ( "Error creating domain search bulk:" , err)
}
bulkID := * response.Data.ID
fmt. Printf ( "Domain Search Bulk created with ID: %d\n " , bulkID)
// Launch the operation
launchResp, err := client. LaunchBulk (models.BulkTypeSearch, bulkID)
if err != nil {
log. Fatal ( "Error launching bulk:" , err)
}
fmt. Printf ( "Bulk launched: %s\n " , launchResp.Data.Message)
// Monitor progress
monitorBulkProgress (client, models.BulkTypeSearch, bulkID)
// Download results
err = client. SaveBulkResults (models.BulkTypeSearch, bulkID, "./domain_search_results.csv" , "full" )
if err != nil {
log. Printf ( "Error downloading results: %v " , err)
} else {
fmt. Println ( "Results saved to ./domain_search_results.csv" )
}
}
Advanced Domain Search with Filtering
func advancedDomainSearch ( client * tomba . Tomba ) {
// Advanced search with department and email type filtering
searchParams := & models . BulkSearchCreateParams {
BulkCreateParams: models . BulkCreateParams {
Name: "Engineering Contacts - Tech Companies" ,
List: "github.com \n atlassian.com \n jira.com \n confluence.com \n bitbucket.com" ,
Sources: true ,
Verify: true ,
},
BulkSearchParams: models . BulkSearchParams {
Maximum: "50" , // Up to 50 emails per domain
EmailType: models . BulkSearchParamsType {
Type: "personal" , // Focus on personal emails
PriorityType: "priority" , // Prioritize personal over generic
},
Department: models . BulkSearchParamsDepartment {
Name: [] string { "engineering" , "software" , "security" }, // Target departments
PriorityType: "only" , // Only these departments
},
},
}
response, err := client. CreateSearchBulk (searchParams)
if err != nil {
log. Printf ( "Error creating advanced search: %v " , err)
return
}
bulkID := * response.Data.ID
fmt. Printf ( "Advanced Domain Search created with ID: %d\n " , bulkID)
// Launch and monitor
client. LaunchBulk (models.BulkTypeSearch, bulkID)
monitorBulkProgress (client, models.BulkTypeSearch, bulkID)
// Download different result types
downloadTypes := [] string { "full" , "valid" , "not_found" }
for _, downloadType := range downloadTypes {
filename := fmt. Sprintf ( "./advanced_search_ %s .csv" , downloadType)
err := client. SaveBulkResults (models.BulkTypeSearch, bulkID, filename, downloadType)
if err == nil {
fmt. Printf ( "Downloaded %s results to %s\n " , downloadType, filename)
}
}
}
Marketing Team Search
func marketingTeamSearch ( client * tomba . Tomba ) {
// Search specifically for marketing contacts
marketingParams := & models . BulkSearchCreateParams {
BulkCreateParams: models . BulkCreateParams {
Name: "Marketing Contacts - B2B SaaS" ,
List: "hubspot.com \n mailchimp.com \n intercom.com \n zendesk.com \n salesforce.com" ,
Sources: true ,
Verify: true ,
},
BulkSearchParams: models . BulkSearchParams {
Maximum: "30" ,
EmailType: models . BulkSearchParamsType {
Type: "all" , // Include all email types
PriorityType: "priority" ,
},
Department: models . BulkSearchParamsDepartment {
Name: [] string { "marketing" , "sales" , "communication" , "pr" },
PriorityType: "priority" , // Prioritize these departments
},
},
}
response, err := client. CreateSearchBulk (marketingParams)
if err != nil {
log. Printf ( "Error creating marketing search: %v " , err)
return
}
bulkID := * response.Data.ID
fmt. Printf ( "Marketing Team Search created with ID: %d\n " , bulkID)
// Launch with progress monitoring
client. LaunchBulk (models.BulkTypeSearch, bulkID)
// Enhanced monitoring with email count tracking
monitorWithEmailCounts (client, models.BulkTypeSearch, bulkID)
}
Batch Domain Processing
func batchDomainSearch ( client * tomba . Tomba , domains [] string , batchSize int ) error {
if len (domains) > 15000 {
return fmt. Errorf ( "too many domains: %d (max: 15000)" , len (domains))
}
// Process in batches for better management
for i := 0 ; i < len (domains); i += batchSize {
end := i + batchSize
if end > len (domains) {
end = len (domains)
}
batch := domains[i:end]
batchNum := (i / batchSize) + 1
fmt. Printf ( "Processing batch %d ( %d domains)... \n " , batchNum, len (batch))
params := & models . BulkSearchCreateParams {
BulkCreateParams: models . BulkCreateParams {
Name: fmt. Sprintf ( "Domain Batch %d - %s " , batchNum, time. Now (). Format ( "Jan 02" )),
List: strings. Join (batch, " \n " ),
Sources: true ,
Verify: true ,
},
BulkSearchParams: models . BulkSearchParams {
Maximum: "25" ,
EmailType: models . BulkSearchParamsType {
Type: "all" ,
PriorityType: "priority" ,
},
},
}
response, err := client. CreateSearchBulk (params)
if err != nil {
log. Printf ( "Error creating batch %d : %v " , batchNum, err)
continue
}
bulkID := * response.Data.ID
// Launch batch
_, err = client. LaunchBulk (models.BulkTypeSearch, bulkID)
if err != nil {
log. Printf ( "Error launching batch %d : %v " , batchNum, err)
continue
}
fmt. Printf ( "Batch %d launched with ID: %d\n " , batchNum, bulkID)
// Small delay between batches
time. Sleep ( 3 * time.Second)
}
return nil
}
Domain Search Management
func manageDomainSearchBulks ( client * tomba . Tomba ) {
// Get all domain search bulks
allBulks, err := client. GetAllSearchBulks ( & models . BulkGetParams {
Page: 1 ,
Limit: 15 ,
Direction: "desc" ,
Filter: "all" ,
})
if err != nil {
log. Printf ( "Error getting search bulks: %v " , err)
return
}
fmt. Printf ( "Total domain search bulks: %d\n " , allBulks.Meta.Total)
// Analyze and manage bulks
for _, bulk := range allBulks.Data {
fmt. Printf ( " \n Bulk: %s (ID: %d ) \n " , bulk.Name, bulk.BulkID)
fmt. Printf ( " Progress: %d%% , Created: %s\n " ,
bulk.Progress, bulk.CreatedAt. Format ( "2006-01-02 15:04" ))
if bulk.TotalEmails != nil {
fmt. Printf ( " Emails Found: %d\n " , * bulk.TotalEmails)
}
if bulk.VerifyCost != nil {
fmt. Printf ( " Verification Cost: %d credits \n " , * bulk.VerifyCost)
}
// Handle completed bulks
if bulk.Progress >= 100 && ! bulk.Used {
handleCompletedBulk (client, bulk)
}
// Handle stuck or failed bulks
if bulk.Progress < 100 && time. Since (bulk.CreatedAt) > 2 * time.Hour {
fmt. Printf ( " ⚠️ Bulk may be stuck (created %v ago) \n " , time. Since (bulk.CreatedAt))
}
}
}
func handleCompletedBulk ( client * tomba . Tomba , bulk models . BulkItem ) {
bulkID := bulk.BulkID
// Download all result types
resultTypes := map [ string ] string {
"full" : "complete results" ,
"valid" : "verified emails only" ,
"not_found" : "domains without results" ,
}
for resultType, description := range resultTypes {
filename := fmt. Sprintf ( "./domain_search_ %d _ %s .csv" , bulkID, resultType)
err := client. SaveBulkResults (models.BulkTypeSearch, bulkID, filename, resultType)
if err == nil {
fmt. Printf ( " ✓ Downloaded %s to %s\n " , description, filename)
} else {
fmt. Printf ( " ✗ Failed to download %s : %v\n " , description, err)
}
}
// Mark as used by renaming
newName := fmt. Sprintf ( "[PROCESSED] %s " , bulk.Name)
renameParams := & models . BulkRenameParams {Name: newName}
client. RenameBulk (models.BulkTypeSearch, bulkID, renameParams)
}
Helper Functions
func monitorBulkProgress ( client * tomba . Tomba , bulkType models . BulkType , bulkID int64 ) {
fmt. Printf ( "Monitoring progress for bulk ID: %d ... \n " , bulkID)
startTime := time. Now ()
for {
progress, err := client. GetBulkProgress (bulkType, bulkID)
if err != nil {
log. Printf ( "Error getting progress: %v " , err)
time. Sleep ( 10 * time.Second)
continue
}
elapsed := time. Since (startTime)
fmt. Printf ( "Progress: %d%% ( %d processed) - Elapsed: %v\n " ,
progress.Progress, progress.Processed, elapsed. Round (time.Second))
if progress.Progress >= 100 {
fmt. Printf ( "✓ Domain search completed in %v ! \n " , elapsed. Round (time.Second))
break
}
time. Sleep ( 15 * time.Second)
}
}
func monitorWithEmailCounts ( client * tomba . Tomba , bulkType models . BulkType , bulkID int64 ) {
fmt. Printf ( "Monitoring bulk %d with email count tracking... \n " , bulkID)
for {
progress, err := client. GetBulkProgress (bulkType, bulkID)
if err != nil {
log. Printf ( "Error getting progress: %v " , err)
time. Sleep ( 15 * time.Second)
continue
}
fmt. Printf ( "Progress: %d%% | Domains: %d | Emails: %d\n " ,
progress.Progress, progress.Processed, progress.ProcessedEmail)
if progress.Progress >= 100 {
fmt. Printf ( "✓ Search completed! Found %d emails from %d domains \n " ,
progress.ProcessedEmail, progress.Processed)
break
}
time. Sleep ( 20 * time.Second)
}
}
Configuration Options
Email Type Filtering
// Personal emails only
EmailType: models . BulkSearchParamsType {
Type: "personal" ,
PriorityType: "only" ,
}
// Generic emails only
EmailType: models . BulkSearchParamsType {
Type: "generic" ,
PriorityType: "only" ,
}
// All types with personal priority
EmailType: models . BulkSearchParamsType {
Type: "all" ,
PriorityType: "priority" ,
}
Department Targeting
// Engineering teams only
Department: models . BulkSearchParamsDepartment {
Name: [] string { "engineering" , "software" , "security" },
PriorityType: "only" ,
}
// Exclude specific departments
Department: models . BulkSearchParamsDepartment {
Name: [] string { "hr" , "accounting" , "legal" },
PriorityType: "exclude" ,
}
// Prioritize business teams
Department: models . BulkSearchParamsDepartment {
Name: [] string { "sales" , "marketing" , "business" },
PriorityType: "priority" ,
}
Best Practices
Clean Domain Lists : Ensure domains are properly formatted without protocols
Set Reasonable Limits : Balance between comprehensive results and processing time
Use Verification : Enable email verification for higher-quality prospect lists
Target Smartly : Use department and email type filters to focus on relevant contacts
Monitor Regularly : Check progress for large bulk operations
Download Multiple Types : Get full, valid, and not_found results for complete analysis
Batch Large Lists : Process very large domain lists in manageable batches
Archive Completed : Keep dashboard organized by archiving old bulks
Track Costs : Monitor verification costs for budget planning
Regular Cleanup : Archive or delete old bulks to maintain performance
Common Use Cases
Lead Generation : Build prospect lists for sales outreach
Competitor Research : Analyze competitor contact structures
Market Expansion : Find contacts in new market segments
Partnership Development : Identify potential integration partners
Content Marketing : Build blogger and influencer contact lists
Account-Based Marketing : Deep-dive into target account contacts
Industry Analysis : Study contact patterns across industries
Result Analysis
The domain search results typically include:
Email Address : Discovered email addresses
Name : Associated contact names when available
Department : Inferred or detected department
Job Title : Contact roles and positions
Verification Status : Email deliverability status
Source : Where the email was discovered
Domain : Source company domain
Social Profiles : Associated social media profiles
Last modified on October 10, 2025