keinsaasforever/gtm-pipeline-skills/gtm-people-enrichment
Claude Code and agent skill by keinsaasforever/gtm-pipeline-skills
- community
Checking that the SKILL.md file is still in the repository.
Enrich contacts with work email, phone number, and/or LinkedIn URL. Use when you have a contact list that needs enrichment before outreach. Email waterfall (FullEnrich → Pipe0), phone (FullEnrich → Pipe0 → BetterContact). Enforces demo mode (email only, no phone). Also triggers on "enrich contacts", "find emails for", "get phone numbers for".
Install
npx vskill@latest install keinsaasforever/gtm-pipeline-skills/gtm-people-enrichmentSKILL.md
People Enrichment
Enrich contacts with work email, phone number, and/or LinkedIn URL. Returns an updated CSV.
Read `~/.claude/skills/gtm-pipeline/_shared/conventions.md` before executing.
When to Use
- You have a contact list and need emails and/or phone numbers
- Contacts from people-search need enrichment before outreach
- A user-provided CSV has names + companies but missing contact info
Inputs
| Input | Required | Source | |
|---|---|---|---|
| Contact CSV | Yes | Contact Filter output (csv/intermediate/contacts_filtered.csv); People Search output if the filter was skipped; or user-provided | |
| LinkedIn profile URLs | Recommended | In CSV or from People Search | |
| Company domains | Recommended | In CSV | |
| Enrichment type | Yes | email, phone, or both |
Demo Mode
When invoked from the demo flow: email only, skip all phone providers entirely.
Cloudflare: BC and FE (like Pipe0) are Cloudflare-fronted — call them with curl + a browser User-Agent (conventions rule #8); never Python requests/urllib.
Provider Selection
Ask the user which provider to use. Default recommendation:
| Priority | Provider | Hit Rate | Cost | Speed | Notes | |
|---|---|---|---|---|---|---|
| 1st | FullEnrich v2 | 80% (SA), 83% (DACH) | 0.8 cr/contact | instant | Clear winner | |
| 2nd | Pipe0 waterfall | 60% (SA), 83% (DACH) | 1.0–3.5 cr/contact | ~3 min/20 contacts | Solid backup | |
| 3rd | BetterContact (email-only) | ~60% test / 14% production SA | 0.35 cr/contact | 30–90 min | Not recommended — slow, unreliable production |
Recommended flow (email waterfall): FE Enrich (v2) → Pipe0 waterfall → BC (last resort). FE is email-first; BC drops to last for email because its async email hit rate is low (~14% production SA). Max 2 attempts per source, then fall through. The order follows the email priority table above (for email, BC ranks below Pipe0, unlike the finder cadence in conventions).
Domain-Identity Cross-Check (critical)
Deliverability status is blind to identity. Providers return DELIVERABLE emails on the wrong company's domain (a genuine wrong-company hit — the exact "made-up address" failure clients fear). Provider status alone is not enough.
MANDATORY before an enriched email is kept:
- The email's domain must belong to the target company — match by domain-root against the target's known domain / company name.
- If the domain is unfamiliar, verify what it actually is (e.g. scrape its title) before trusting it.
- Drop identity mismatches even when status is
DELIVERABLE. - A company's mail domain can differ from its website. Accept a second domain only when the company's own evidence
ties it to it: the address on its imprint or contact page, or a domain that redirects to the website. A similar name is not evidence. Without this, the right person's address on the company's mail domain is dropped as a mismatch.
This is the real anti-"made-up-address" guard; the sanitize.py deliverability filter (below) is only the last net.
Phone
Skip entirely in demo mode.
| Priority | Provider | Hit Rate | Cost | Speed | Notes | |
|---|---|---|---|---|---|---|
| 1st | FullEnrich v2 | ~60% DACH | ~0.8 cr/contact | instant | Good DACH coverage. Prefer most_probable_phone.number over phones[0] (phones[0] can be landline, most_probable is mobile) | |
| 2nd | Pipe0 phone waterfall | ~92% DACH (n=74) · 0% SA | 2–7 cr/contact | ~30s/batch | Response field: mobile (not phone). Works reliably as FE fallback — on 7 FE contacts missing phones, recovered 5 (71%). Also strong as primary when contacts come from Pipe0 search (68/74 = 92%) | |
| 3rd | BetterContact | 13–74% (~22% SA, ~53% DACH) | ~1–2 cr/contact | 5–10+ min for small batches | Unreliable speed — took 10+ min for 2 contacts in DACH test. Retest before production |
LinkedIn URL (when missing)
- Pipe0 `people:profileurl:name@1` — 0.60 cr/person, needs name + company_name + location_hint
- PhantomBuster Profile Scraper (config key:
PB_AGENT_PROFILE) — scrape full profile data from existing LinkedIn URL; use/phantombusterskill with phantom name "LinkedIn Profile Scraper" and CSV path. See_shared/phantombuster.md.
Execution Protocol
1. Assess Input Data
- Check what fields are available (LinkedIn URL, domain, name, company)
- Determine which enrichment types are needed
- Estimate credit cost:
n_contacts × max_cost_per_record - Confirm credit balance with user before proceeding
2. Test Batch (5–10 contacts)
- Run chosen provider on 5–10 contacts in production
- Inspect every result: email validity status, phone format, match accuracy
- Check hit rate — if below 10%, investigate before proceeding
3. Review with User
- Present test results with hit rate, status breakdown, sample data
- Confirm provider choice and credit spend for full batch
- Get approval
4. Full Batch
- Split into chunks of max 100 contacts per request (all providers)
- Save request/task IDs immediately
- Poll with appropriate timeouts:
- FE: 15s interval, 600s timeout (usually instant)
- Pipe0: 30s interval, 600s timeout (≤100 contacts)
- BC phone: 30s interval, 900s timeout
- BC email: 60s interval, 3600s timeout
- Save results incrementally after each batch
5. Fallback Pass
- Identify contacts with missing email/phone after primary provider
- Run fallback provider on misses only
- Merge results
6. Final Output
- Merge all provider results into
csv/intermediate/contacts_enriched.csv— keep every field (email_source/phone_source,email_status, provider labels), per conventions rule #6 - Confirm each email passed the domain-identity cross-check above before it can ship
- Sanitize before the lead-facing view — run the shared sanitizer (do not reimplement); it drops bad emails, strips provider/source labels + internal status codes, and drops empty columns. See conventions Output Sanitization:
- Deliverability policy is applied by
sanitize.pyviaemail_policy: defaultstandardkeeps DELIVERABLE + HIGH_PROBABILITY + CATCH_ALL and drops UNKNOWN/RISKY/invalid;strictadditionally drops catch-all - Write the sanitized rows to
csv/output/contacts_enriched.csv
Provider 1: FullEnrich v2 (Email + Phone)
Endpoint: POST https://app.fullenrich.com/api/v2/contact/enrich/bulk Auth: Authorization: Bearer $FULLENRICH_API_KEY
Submit (max 100 contacts/batch)
For phone: "enrich_fields": ["contact.phones"] or both: ["contact.emails", "contact.phones"]
Poll
Done when: response["status"] == "FINISHED" Speed: usually instant — often finished before first poll. Use 15s interval, 600s timeout.
Parse
Key Notes
- Cloudflare-fronted — call with
curl+ a browserUser-Agent(conventions rule #8); never Pythonrequests/urllib - Base URL is
app.fullenrich.com(NOTapi.fullenrich.com) - Use v2 (not v1)
- Max 100 contacts per batch
- Submit response key is
enrichment_id(UUID) - Email:
contact_info.most_probable_work_email.email - Phone:
contact_info.phones[0].number - If credits run out mid-batch:
status = "CREDITS_INSUFFICIENT", partial results returned - Email status values:
DELIVERABLE,HIGH_PROBABILITY,CATCH_ALL
Cost
~0.8 credits/contact
Docs
https://docs.fullenrich.com
Provider 2: Pipe0 Email Waterfall
Pipe ID: people:workemail:profileurl:waterfall@1 Auth: Authorization: Bearer $PIPE0_API_KEY Use curl — Python requests blocked by Cloudflare.
Submit
Key Notes
- Submit response key is `id` (not
task_id) — use this value for polling:GET /pipes/check/{id} email_validation_statusfield is also returned alongsidework_emailin each record- Email quality: ~15–25% of hits may be stale (old employer email) for EU audiences. Waterfall picks up the most recent known email regardless of current role. Always post-filter: remove personal domains (gmail, yahoo, etc.) and cross-check email domain against current company. In EU SME test: 37/43 raw hits, 30/43 valid after filtering 7 stale/personal.
Poll
Done when: status == "completed". Use 30s interval, 600s timeout (~3 min for 43 contacts). Keep batches ≤100 contacts.
Parse
Post-filtering (Recommended)
After enrichment, filter out stale/personal emails:
Waterfall Providers & Cost
| Provider | Cost | |
|---|---|---|
| HunterMail | 1.00 cr | |
| LeadMagic | 2.00 cr | |
| FindyMail | 2.00 cr | |
| Crustdata | 3.50 cr |
Stops at first hit. Total: 1.00–3.50 cr/contact.
Provider 3: BetterContact (Email or Phone)
Endpoint: POST https://app.bettercontact.rocks/api/v2/async Auth: X-API-KEY: $BETTERCONTACT_API_KEY
Submit (max 100 contacts/batch)
Poll
Done when: response["status"] == "terminated" (NOT "completed")
- Phone only: ~3–5 min/100 contacts. Use 900s timeout.
- Email only or both: 30–90 min. Use 3600s timeout.
on hold= credits exhausted, batch paused — no cancel endpoint.
This is the start of the file. Read the full SKILL.md on GitHub.
Security
- Security scanPassed, 100 of 100Pattern checks on the skill's files.
- Model reviewNot runA model review is scheduled for the next rescan.
Quality evaluation
- Task evaluationNot runNo evaluation yet. Run one in Skill Studio.
Source
- SKILL.md in the repositoryCheckingskills/gtm-people-enrichment/SKILL.md
Popularity
- Repository stars
- 75
- Repository forks
- 8
- 7-day trend score
- 21
Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.
Works with
Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.
- Claude Code
- Cursor
- GitHub Copilot
- Windsurf
- Codex
- Gemini CLI
- Cline
- Amp
- Roo Code
- Goose
- Continue
- Kilo Code
- Junie
- Trae
- OpenHands
- Qwen Code
- AI Agent
- Tabnine Chat
- Sourcegraph Cody
- Amazon Q
- Firebase Genkit
- Sweep
- Devin
- Phind
- Mentat
- Claude Desktop
- Aider
- GPT Pilot
- Plandex
- bolt.new
- v0
- Replit Agent
- Anse
- TypingMind
- BetterChatGPT
- LibreChat
- Warp AI
- Pieces
- Fig AI
Embed badge
[](https://verified-skill.com/skills/keinsaasforever/gtm-pipeline-skills/gtm-people-enrichment)