Enrichment Guide
Turn any domain into 40+ fields of company intelligence — firmographics, social profiles, AI insights, and B2B Match scoring.
You can enrich companies one-by-one or in bulk from the Dashboard — search a domain, upload a CSV, and export the results. No code required.
Why Async?
Vera uses an asynchronous pattern because high-quality data requires web scraping, AI analysis, and multi-source validation — typically 5-15 seconds per company. You submit a domain, get a job ID, and poll for results. This lets you fire-and-forget or process many companies in parallel.
The Enrichment Flow
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ POST │ │ Poll │ │ Get │
│ /enrich │ ──► │ /jobs/{id} │ ──► │ Results │
│ │ │ │ │ │
│ Returns │ │ status: │ │ status: │
│ jobId │ │ processing │ │ completed │
└─────────────┘ └─────────────┘ └─────────────┘
Step 1: Submit Request
POST a domain to /enrich to start a job. See the Quickstart for full request examples. You'll get back a jobId to poll.
The url field accepts any format: stripe.com, www.stripe.com, https://stripe.com/pricing — all normalize to the same domain.
jobId instead of creating a new job.Step 2: Poll for Results
Poll /enrich/{id} until the status resolves:
| Status | Description |
|---|---|
pending | Queued, waiting to start |
processing | Actively running |
completed | Finished — data available |
failed | Error occurred |
- JavaScript
- Python
async function enrichCompany(domain) {
const startResponse = await fetch('https://api.veraenrich.com/enrich', {
method: 'POST',
headers: {
'Authorization': `Bearer ${process.env.VERA_API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ url: domain })
});
const { jobId } = await startResponse.json();
for (let i = 0; i < 60; i++) {
const pollResponse = await fetch(
`https://api.veraenrich.com/enrich/${jobId}`,
{ headers: { 'Authorization': `Bearer ${process.env.VERA_API_KEY}` } }
);
const result = await pollResponse.json();
if (result.status === 'completed') return result.data;
if (result.status === 'failed') throw new Error(result.error);
await new Promise(r => setTimeout(r, 1000));
}
throw new Error('Timeout waiting for enrichment');
}
import os, time, requests
def enrich_company(domain):
headers = {'Authorization': f'Bearer {os.environ["VERA_API_KEY"]}'}
response = requests.post(
'https://api.veraenrich.com/enrich',
headers={**headers, 'Content-Type': 'application/json'},
json={'url': domain}
)
response.raise_for_status()
job_id = response.json()['jobId']
for _ in range(60):
result = requests.get(
f'https://api.veraenrich.com/enrich/{job_id}',
headers=headers
).json()
if result['status'] == 'completed': return result['data']
if result['status'] == 'failed': raise Exception(result['error'])
time.sleep(1)
raise Exception('Timeout waiting for enrichment')
Error Handling
| Error | Cause | Solution |
|---|---|---|
AUTHENTICATION_FAILED | Invalid API key | Check your API key |
RATE_LIMIT_EXCEEDED | Too many requests | Implement backoff — see Rate Limits |
VALIDATION_ERROR | Invalid domain | Check the URL format |
JOB_NOT_FOUND | Invalid job ID | Verify the jobId from the original response |
For production, add exponential backoff on 429 responses. See Rate Limits for retry patterns.
Data Quality
Every enrichment includes a confidence score (0-100) and a sources array:
| Score | Quality | Description |
|---|---|---|
| 90+ | High | Multiple sources confirmed |
| 70-89 | Medium | Good data from primary sources |
| 50-69 | Low | Limited data, some inferred |
| Below 50 | Very Low | Use with caution |
See Company Schema for all available fields and Data Sources for how data is collected.
Next Steps
- B2B Match — Get sales angles and partnership insights for every company
- Bulk Enrichment — Enrich many companies at once
- Rate Limits — Understand your quota
- Integration Patterns — Background, blocking, and cache-first patterns
- Competitor Research — Map competitive landscapes from domains
- Target Account Lists — Build and score prospect lists