Skip to main content

Lead Enrichment Guide

Learn how to enrich your leads with company data using WhizoAI’s AI-powered enrichment system. This guide covers everything from basic enrichment to advanced optimization strategies.

What is Lead Enrichment?

Lead enrichment automatically gathers additional information about your contacts using their email addresses. WhizoAI’s multi-agent system extracts company data from websites, social profiles, and public sources to help you:
  • Qualify leads more effectively
  • Personalize outreach at scale
  • Build comprehensive customer profiles
  • Identify decision-makers and stakeholders

Basic Enrichment

Start with a simple enrichment request:
curl -X POST "https://api.whizo.ai/v1/ai-enrichment" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "data": [
      {
        "email": "[email protected]",
        "name": "John Smith"
      }
    ],
    "fields": [
      {
        "name": "company_name",
        "description": "Extract the company name",
        "type": "text"
      },
      {
        "name": "industry",
        "description": "What industry is this company in?",
        "type": "text"
      },
      {
        "name": "employee_count",
        "description": "Number of employees (approximate range)",
        "type": "text"
      }
    ]
  }'
Response includes a job ID for tracking progress:
{
  "success": true,
  "data": {
    "jobId": "enrich_abc123",
    "status": "queued",
    "totalRows": 1,
    "estimatedCredits": 3
  }
}

Designing Effective Prompts

The quality of your results depends heavily on how you define your fields. Follow these best practices:

Good Field Definitions

{
  "name": "company_size",
  "description": "Categorize company size: Startup (1-50), Small (51-200), Medium (201-1000), Large (1001+)",
  "type": "text"
}

Poor Field Definitions

{
  "name": "info",
  "description": "Get info",
  "type": "text"
}
Key Tips:
  • Be specific about what you want
  • Provide examples of expected output
  • Use clear, actionable language
  • Avoid vague terms like “info” or “data”

Real-Time Progress with SSE Streaming

Monitor enrichment progress in real-time using Server-Sent Events:
const eventSource = new EventSource(
  'https://api.whizo.ai/v1/ai-enrichment/enrich_abc123/stream',
  {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    }
  }
);

eventSource.addEventListener('progress', (event) => {
  const data = JSON.parse(event.data);
  console.log(`Progress: ${data.rowsProcessed}/${data.totalRows}`);
  console.log(`Success rate: ${data.successRate}%`);
});

eventSource.addEventListener('row_completed', (event) => {
  const data = JSON.parse(event.data);
  console.log(`Completed row ${data.rowIndex}: ${data.email}`);
});

eventSource.addEventListener('completed', (event) => {
  console.log('Enrichment complete!');
  eventSource.close();
});

eventSource.addEventListener('error', (event) => {
  console.error('Stream error:', event);
  eventSource.close();
});

Batch Enrichment

Process multiple leads efficiently:
import requests
import csv

# Read contacts from CSV
contacts = []
with open('leads.csv', 'r') as file:
    reader = csv.DictReader(file)
    for row in reader:
        contacts.append({
            'email': row['email'],
            'name': row['name'],
            'company': row['company']
        })

# Start enrichment job
response = requests.post(
    'https://api.whizo.ai/v1/ai-enrichment',
    headers={
        'Authorization': 'Bearer YOUR_API_KEY',
        'Content-Type': 'application/json'
    },
    json={
        'data': contacts[:100],  # Process first 100
        'fields': [
            {
                'name': 'company_website',
                'description': 'Find the company website URL',
                'type': 'text'
            },
            {
                'name': 'company_description',
                'description': 'Brief description of what the company does',
                'type': 'text'
            },
            {
                'name': 'funding_stage',
                'description': 'Company funding stage: Bootstrap, Seed, Series A/B/C, etc.',
                'type': 'text'
            },
            {
                'name': 'technologies_used',
                'description': 'List of technologies or platforms the company uses',
                'type': 'text'
            }
        ]
    }
)

job_id = response.json()['data']['jobId']
print(f'Job started: {job_id}')

Downloading Results

Once enrichment is complete, download results in your preferred format:

JSON Format

curl -X GET "https://api.whizo.ai/v1/ai-enrichment/enrich_abc123/results?format=json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o results.json

CSV Format

curl -X GET "https://api.whizo.ai/v1/ai-enrichment/enrich_abc123/results?format=csv" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o results.csv

Programmatic Download

const response = await fetch(
  'https://api.whizo.ai/v1/ai-enrichment/enrich_abc123/results?format=json',
  {
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY'
    }
  }
);

const results = await response.json();

// Process enriched data
results.forEach(row => {
  console.log(`${row.email}: ${row.enriched_data.company_name}`);
});

Advanced Use Cases

Sales Intelligence

Enrich leads with detailed company intelligence:
{
  "fields": [
    {
      "name": "company_revenue",
      "description": "Estimated annual revenue range",
      "type": "text"
    },
    {
      "name": "key_decision_makers",
      "description": "Names and titles of key executives (CEO, CTO, etc.)",
      "type": "text"
    },
    {
      "name": "recent_news",
      "description": "Recent news, funding announcements, or major changes",
      "type": "text"
    },
    {
      "name": "tech_stack",
      "description": "Technologies and platforms used by the company",
      "type": "text"
    }
  ]
}

Market Research

Gather competitive intelligence:
{
  "fields": [
    {
      "name": "target_market",
      "description": "Who are their primary customers? (B2B, B2C, Industry)",
      "type": "text"
    },
    {
      "name": "product_offerings",
      "description": "List their main products or services",
      "type": "text"
    },
    {
      "name": "pricing_model",
      "description": "How do they charge? (Subscription, One-time, Usage-based)",
      "type": "text"
    },
    {
      "name": "competitors",
      "description": "Who are their main competitors?",
      "type": "text"
    }
  ]
}

Recruitment Screening

Enrich candidate profiles:
{
  "fields": [
    {
      "name": "current_company_culture",
      "description": "Describe the work culture at their current company",
      "type": "text"
    },
    {
      "name": "company_growth",
      "description": "Is the company growing, stable, or declining?",
      "type": "text"
    },
    {
      "name": "company_benefits",
      "description": "What benefits or perks does the company offer?",
      "type": "text"
    }
  ]
}

Cost Optimization

Minimize Credit Usage

  1. Use Discovery Agent First: Extract domains for free before enrichment
  2. Start Small: Test with 5-10 rows before processing thousands
  3. Be Specific: Focused prompts require less AI processing
  4. Avoid Redundancy: Don’t ask for the same information multiple ways
  5. Batch Wisely: Process in batches of 50-100 for optimal performance

Credit Cost Breakdown

AgentOperationCost
DiscoveryExtract domain from email0 credits (free)
ProfileScrape company website1-3 credits
GeneralCustom field extraction1-3 credits per field

Example Cost Calculation

Enriching 100 leads with 4 custom fields:
- Discovery: 100 × 0 = 0 credits
- Profile: 100 × 2 = 200 credits (average)
- General: 100 × 4 fields × 2 = 800 credits (average)
Total: ~1,000 credits

Error Handling

Handle errors gracefully in your application:
import requests
import time

def enrich_with_retry(data, fields, max_retries=3):
    for attempt in range(max_retries):
        try:
            response = requests.post(
                'https://api.whizo.ai/v1/ai-enrichment',
                headers={'Authorization': 'Bearer YOUR_API_KEY'},
                json={'data': data, 'fields': fields},
                timeout=30
            )
            response.raise_for_status()
            return response.json()

        except requests.exceptions.HTTPError as e:
            if e.response.status_code == 429:  # Rate limited
                wait_time = int(e.response.headers.get('Retry-After', 60))
                print(f'Rate limited. Waiting {wait_time}s...')
                time.sleep(wait_time)
                continue

            elif e.response.status_code == 402:  # Insufficient credits
                print('Insufficient credits. Please add credits to continue.')
                return None

            else:
                print(f'HTTP error: {e}')
                if attempt < max_retries - 1:
                    time.sleep(2 ** attempt)  # Exponential backoff
                    continue
                raise

        except requests.exceptions.RequestException as e:
            print(f'Request failed: {e}')
            if attempt < max_retries - 1:
                time.sleep(2 ** attempt)
                continue
            raise

    return None

Best Practices

  1. Test First: Always test with a small sample before processing your entire list
  2. Monitor Progress: Use SSE streaming to track long-running jobs
  3. Handle Partial Failures: Some rows may fail while others succeed
  4. Validate Results: Review enriched data for accuracy before using in production
  5. Respect Privacy: Only enrich leads who have consented to data collection
  6. Cache Results: Store enriched data to avoid reprocessing the same leads

Rate Limits and Concurrency

Different plans have different limits:
PlanConcurrent JobsRows Per JobRate Limit
Free110010/hour
Starter250050/hour
Pro52,000200/hour
Enterprise1010,0001000/hour
Plan your enrichment batches accordingly to avoid rate limiting.

Monitoring Job Status

Check job status programmatically:
async function waitForCompletion(jobId, maxWaitTime = 600000) {
  const startTime = Date.now();

  while (Date.now() - startTime < maxWaitTime) {
    const response = await fetch(
      `https://api.whizo.ai/v1/ai-enrichment/${jobId}`,
      {
        headers: { 'Authorization': 'Bearer YOUR_API_KEY' }
      }
    );

    const data = await response.json();
    const status = data.data.status;

    if (status === 'completed') {
      return { success: true, data: data.data };
    } else if (status === 'failed') {
      return { success: false, error: data.data.error };
    }

    // Job still processing
    await new Promise(resolve => setTimeout(resolve, 5000)); // Wait 5s
  }

  return { success: false, error: 'Timeout waiting for job completion' };
}

Integration Examples

CRM Integration

Enrich contacts in your CRM automatically:
# Pseudo-code for CRM integration
def enrich_crm_contacts():
    # 1. Fetch unprocessed contacts from CRM
    contacts = crm.get_contacts(enrichment_status='pending')

    # 2. Start enrichment job
    job = start_enrichment(contacts)

    # 3. Wait for completion
    results = wait_for_results(job['jobId'])

    # 4. Update CRM with enriched data
    for result in results:
        crm.update_contact(
            email=result['email'],
            company=result['enriched_data']['company_name'],
            industry=result['enriched_data']['industry'],
            size=result['enriched_data']['employee_count']
        )

    # 5. Mark as processed
    crm.update_contacts(emails, enrichment_status='completed')

Email Marketing

Segment audiences based on enriched data:
def segment_by_company_size(enriched_data):
    segments = {
        'enterprise': [],
        'mid_market': [],
        'smb': []
    }

    for lead in enriched_data:
        size = lead['enriched_data'].get('employee_count', '')

        if 'Large' in size or '1000+' in size:
            segments['enterprise'].append(lead['email'])
        elif 'Medium' in size:
            segments['mid_market'].append(lead['email'])
        else:
            segments['smb'].append(lead['email'])

    return segments

Troubleshooting

Common Issues

Issue: “No domain found for email”
  • Solution: The email domain couldn’t be extracted. Verify the email format is valid.
Issue: “Website not accessible”
  • Solution: The company website may be down or blocking scrapers. Try again later.
Issue: “Insufficient data to extract”
  • Solution: The website doesn’t contain the requested information. Refine your prompts or try different fields.
Issue: Rate limiting errors
  • Solution: Spread out your requests or upgrade to a higher plan for increased limits.

Support and Resources

For questions or feature requests, reach out to our support team.