Bulk Enrichment
Enrich up to 1,000 companies in a single request — build target account lists, score your CRM, or research an entire market segment at once.
Prefer a visual workflow? Upload a CSV of domains in the Dashboard and export enriched results — no API integration needed. See Target Account Lists for a step-by-step walkthrough.
Submit a Batch
curl -X POST https://api.veraenrich.com/enrich/bulk \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{"domains": ["stripe.com", "shopify.com", "twilio.com"]}'
Response (202 Accepted):
{
"status": "processing",
"batchId": "batch-uuid-here",
"totalDomains": 3,
"queuedDomains": 3,
"invalidDomains": 0,
"estimatedDurationMin": 1,
"message": "Started processing 3 domains (~1 min)"
}
Check Batch Status
curl https://api.veraenrich.com/enrich/bulk/BATCH_ID \
-H "Authorization: Bearer YOUR_API_KEY"
{
"batchId": "batch-uuid-here",
"status": "processing",
"totalDomains": 100,
"processedCount": 45,
"succeededCount": 42,
"failedCount": 3,
"progress": 45,
"errors": [
{"domain": "invalid.xyz", "error": "Unable to reach website"}
]
}
| Status | Description |
|---|---|
processing | Actively being processed |
completed | All domains processed |
failed | Batch failed to start (all domains invalid) |
Implementation
- JavaScript
- Python
async function bulkEnrich(domains) {
const headers = {
'Authorization': `Bearer ${process.env.VERA_API_KEY}`,
'Content-Type': 'application/json'
};
const response = await fetch('https://api.veraenrich.com/enrich/bulk', {
method: 'POST',
headers,
body: JSON.stringify({ domains })
});
const { batchId } = await response.json();
// Poll for completion (~3s per domain, 5s interval)
const maxAttempts = Math.ceil((domains.length * 3) / 5) + 20;
for (let i = 0; i < maxAttempts; i++) {
const status = await fetch(
`https://api.veraenrich.com/enrich/bulk/${batchId}`,
{ headers: { 'Authorization': headers.Authorization } }
).then(r => r.json());
console.log(`Progress: ${status.progress}%`);
if (status.status === 'completed') return status;
if (status.status === 'failed') throw new Error('Batch failed');
await new Promise(r => setTimeout(r, 5000));
}
throw new Error('Timeout waiting for batch');
}
import os, time, requests
def bulk_enrich(domains):
headers = {'Authorization': f'Bearer {os.environ["VERA_API_KEY"]}'}
response = requests.post(
'https://api.veraenrich.com/enrich/bulk',
headers={**headers, 'Content-Type': 'application/json'},
json={'domains': domains}
)
response.raise_for_status()
batch_id = response.json()['batchId']
# ~3s per domain, poll every 5s
max_attempts = (len(domains) * 3) // 5 + 20
for _ in range(max_attempts):
batch = requests.get(
f'https://api.veraenrich.com/enrich/bulk/{batch_id}',
headers=headers
).json()
print(f"Progress: {batch['progress']}%")
if batch['status'] == 'completed': return batch
if batch['status'] == 'failed': raise Exception('Batch failed')
time.sleep(5)
raise Exception('Timeout waiting for batch')
Domain Handling
Accepted formats: stripe.com, www.stripe.com, https://stripe.com, https://stripe.com/pricing — all normalize to the same domain. Duplicates are automatically deduplicated.
Rejected: empty strings, IP addresses, invalid TLDs. Invalid domains are reported in the response errors array and don't block the batch.
Limits
| Limit | Value |
|---|---|
| Max domains per batch | 1,000 |
| Concurrent batches | 1 per team |
| Processing speed | ~3s per domain |
Error Handling
Batch-level errors are returned as HTTP status codes (see Error Codes). Individual domain failures appear in the errors array — the batch continues processing remaining domains.
Next Steps
- B2B Match — Get sales angles and partnership insights for every enriched company
- Enrichment Guide — Single company enrichment in depth
- Target Account Lists — End-to-end workflow for building scored prospect lists
- API Reference — Full endpoint docs