Claude-skill-registry lead-enrichment
Find 5-10 key decision makers per company with verified emails using Parallel, Apollo, and MillionVerifier APIs
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/lead-enrichment" ~/.claude/skills/majiayu000-claude-skill-registry-lead-enrichment && rm -rf "$T"
skills/data/lead-enrichment/SKILL.mdLead Enrichment
Use this skill when: user asks to "enrich leads", "find decision makers", "get contacts for companies", "find emails", or any request to turn a company list into actionable contacts.
Overview
This skill takes a list of companies and finds key decision makers with:
- Full name
- Job title
- Work email (verified)
- LinkedIn URL
Uses a 3-stage pipeline:
- Parallel API - Primary contact discovery
- Apollo API - Email enrichment fallback
- MillionVerifier - Email verification
Pre-flight Checks
Required API Keys
Before running enrichment, verify these keys exist:
| Key | Service | Get it at |
|---|---|---|
| Parallel (contact discovery) | platform.parallel.ai |
| Apollo (email enrichment) | app.apollo.io |
| MillionVerifier (verification) | app.millionverifier.com |
If keys are missing:
- Ask user which keys they have
- Guide them to sign up for missing services
- Explain what each service does and approximate cost
- Have them add keys to
file.env
Required Input
- Company list: CSV or JSON with at minimum:
- Company name
- Website (for domain extraction)
- Optional: ICP segment, priority score, target titles
Stage 1: Contact Discovery (Parallel API)
Purpose
Find 5-10 decision makers per company from public sources.
Process
-
For each company, call Parallel Task API with:
- Company name
- Website domain
- Target titles to find
-
Extract from results:
- Person name
- Title
- Email (if public)
- LinkedIn URL
Target Titles (customize per ICP)
Executive level:
- Founder, CEO, President, Owner
- CTO, CIO, COO, CFO
VP level:
- VP Supply Chain, VP Procurement, VP Sourcing
- VP Operations, VP Product, VP Engineering
Director level:
- Director Supply Chain, Director Procurement
- Director Operations, Director Product
Manager level:
- Product Manager, Procurement Manager
- Merchandise Manager, Buyer
Parallel API Call
from parallel_web import Parallel client = Parallel(api_key=os.getenv("PARALLEL_API_KEY")) result = client.task.create( prompt=f"""Find up to 5 key decision makers at {company_name}. Website: {website} For each person, extract: - Full name - Job title - Work email (if available) - LinkedIn URL Target titles: {target_titles} """, processor="base" # or "core", "pro" )
Output
{ "company": "Example Corp", "contacts": [ { "name": "John Smith", "title": "VP Supply Chain", "email": "john.smith@example.com", "linkedin": "linkedin.com/in/johnsmith" } ] }
Stage 2: Email Enrichment (Apollo API)
Purpose
Find emails for contacts that Parallel didn't return emails for.
Process
-
Filter contacts where email is null/empty
-
For each contact, call Apollo People Match:
- First name
- Last name
- Company domain (extracted from website)
-
Apollo returns:
- Work email
- LinkedIn URL (backup)
- Verified title
Apollo API Call
import requests def apollo_enrich(first_name, last_name, domain): url = "https://api.apollo.io/v1/people/match" headers = { "Content-Type": "application/json", "Cache-Control": "no-cache", "X-Api-Key": os.getenv("APOLLO_API_KEY") } data = { "first_name": first_name, "last_name": last_name, "domain": domain } response = requests.post(url, headers=headers, json=data) return response.json()
Rate Limits
- 0.5 sec between requests (be gentle)
- 60 sec wait on 429 errors
- Bulk endpoint available for up to 10 at once
Stage 3: Email Verification (MillionVerifier)
Purpose
Verify all discovered emails before outreach.
Process
- Collect all emails (from Parallel + Apollo)
- Verify each with MillionVerifier API
- Score quality: good, bad, risky, unknown
MillionVerifier API Call
import requests def verify_email(email): url = f"https://api.millionverifier.com/api/v3/?api={api_key}&email={email}" response = requests.get(url) return response.json()
Response Fields
| Field | Values | Meaning |
|---|---|---|
| good, bad, risky, unknown | Overall quality |
| ok, catch_all, unknown, invalid | Specific result |
| 1, 2, 3, 6 | Numeric code |
| true/false | Is it a role address (info@, sales@) |
| true/false | Is it a free email provider |
Quality Interpretation
| Quality | Action |
|---|---|
| good | Safe to send |
| risky | Send with caution, may bounce |
| bad | Do not send |
| unknown | Manual review |
Flag Role Addresses
Role addresses (info@, sales@, support@) have lower response rates. Flag them:
- Still usable but deprioritize
- Look for personal emails instead
- Note in output for campaign decisions
Progress Tracking
Resume Capability
Store progress in JSONL files for resumability:
leads/progress/ parallel.jsonl - Company + contacts + status apollo.jsonl - Contact + email + status millionverifier.jsonl - Email + quality + status
JSONL Format
{"company": "Example Corp", "status": "done", "contacts": [...]} {"company": "Another Inc", "status": "done", "contacts": [...]}
Resume Logic
Before processing:
- Load existing progress file
- Build set of already-processed items
- Skip items in the set
- Append new results to progress file
Output Format
Final CSV
company,segment,website,person1_name,person1_title,person1_email,person1_linkedin,person2_name,person2_title,person2_email,person2_linkedin,...
Up to 5 contacts per company (person1 through person5).
Final JSON
{ "company": "Example Corp", "segment": "Tier1_Gloves", "website": "example.com", "contacts": [ { "name": "John Smith", "title": "VP Supply Chain", "email": "john.smith@example.com", "email_quality": "good", "linkedin": "linkedin.com/in/johnsmith" } ] }
Execution Flow
Option A: Use Existing Scripts
If
pga-2026/scripts/enrichment/ exists with:
enrich_contacts_parallel.pyenrich_emails_apollo.pyverify_emails_millionverifier.py
Run them in sequence:
uv run pga-2026/scripts/enrichment/enrich_contacts_parallel.py uv run pga-2026/scripts/enrichment/enrich_emails_apollo.py uv run pga-2026/scripts/enrichment/verify_emails_millionverifier.py
Option B: Manual Enrichment
For small lists (under 10 companies):
- Use Parallel MCP tool directly for contact discovery
- Use Apollo API calls for missing emails
- Use MillionVerifier for verification
Option C: Create New Scripts
For new campaigns without existing scripts:
- Create script directory:
[campaign]/scripts/enrichment/ - Create 3 stage scripts based on templates
- Create progress tracking directory
- Run pipeline
Error Handling
API Failures
| Error | Action |
|---|---|
| 401 Unauthorized | Check API key is valid |
| 429 Rate Limited | Wait 60 sec, retry |
| 500 Server Error | Wait, retry up to 3 times |
| Timeout | Retry with longer timeout |
Missing Data
| Issue | Fallback |
|---|---|
| No contacts found (Parallel) | Manual web search |
| No email found (Apollo) | Try LinkedIn outreach |
| Bad email (MillionVerifier) | Remove from list |
Quality Checklist
Before delivering enriched list:
- All companies processed (check progress files)
- Emails verified (good/risky/bad flagged)
- Role addresses flagged (info@, sales@)
- LinkedIn URLs present for contacts
- Output format matches user request (CSV or JSON)
- No duplicate contacts across companies
Cost Awareness
Approximate costs (check current pricing):
| Service | Cost |
|---|---|
| Parallel | ~$0.01-0.05 per task |
| Apollo | Credits-based, varies by plan |
| MillionVerifier | ~$0.0003 per email |
For 100 companies with 5 contacts each:
- Parallel: 100 tasks
- Apollo: ~200 email lookups (assuming 40% need enrichment)
- MillionVerifier: ~500 verifications
This skill is generic - works for any campaign, not just Performance Leather.