GTM Enrichment — Smart (Multi-Provider Waterfall)
SkillCommunicationMulti-provider waterfall lead enrichment. Takes an email (+ optional name) and returns person + company data by cross-referencing cheap APIs first, using expensive AI agents only as fallback. Cost-efficient (~$0.04-$0.10/lead) with confidence scoring and full error visibility.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the GTM Enrichment — Smart (Multi-Provider Waterfall) skill
What this skill tells your AI
The instructions your AI receives, as published by gooseworks-ai/goose-skills in skills/lead-generation/capabilities/gtm-enrichment-smart/SKILL.md and read by ahel’s review.
Setup
Choose the available runtime before doing any credential setup:
- Terminal-free client: skip the shell commands below. Use connected MCP tools. For ScrapeCreators operations, read
scrapecreators-apiand prefercall_data_provider. If a required enrichment provider has no connected tool, report that part of the waterfall as unavailable rather than fabricating enrichment data. - Local terminal: use the GooseWorks credentials and proxy commands below.
Read your credentials from ~/.gooseworks/credentials.json:
export GOOSEWORKS_API_KEY=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json'))['api_key'])")
export GOOSEWORKS_API_BASE=$(python3 -c "import json;print(json.load(open('$HOME/.gooseworks/credentials.json')).get('api_base','https://api.gooseworks.ai'))")
If ~/.gooseworks/credentials.json does not exist, tell the user to run: npx gooseworks login
The local proxy endpoints use Bearer auth: -H "Authorization: Bearer $GOOSEWORKS_API_KEY". ScrapeCreators operation descriptions below remain environment-neutral in both runtimes.
Enrich a lead from an email address (+ optional name) using a waterfall strategy: start with cheap APIs ($0.01 each), cross-reference for confidence, then use expensive AI agents only for gaps. Spends proportionally to lead quality.
Cost: $0.04 (best) to ~$0.12 (typical with buying signals) to ~$0.26 (worst, Sixtyfour fallback) Latency: ~5-15s typical, up to 60s if Sixtyfour fallback triggers
Input
Required:
- email — the lead's email address (e.g.,
jane@acme.com)
Optional:
- name — full name if known (improves match rate)
Workflow
Step 0: Extract Domain + Free Email Check
Extract the domain from the email. Check if it's a free email provider.
Free email providers (skip Brand.dev if match): gmail.com, yahoo.com, hotmail.com, outlook.com, aol.com, icloud.com, mail.com, protonmail.com, zoho.com, yandex.com, gmx.com, live.com
Set is_free_email = true/false — this gates whether Brand.dev runs in Phase 1.
PHASE 1 — Core (always run, parallel) — ~$0.03-$0.06
Run ALL of these simultaneously:
1a. Apollo People Match ($0.01):
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"apollo","path":"/api/v1/people/match"}'
"email": "{email}",
"reveal_personal_emails": true
}'
Extract: person.name, person.title, person.linkedin_url, person.city, person.state, person.country, person.organization.name, person.organization.id (save org_id for Phase 4), person.organization.industry, person.organization.estimated_num_employees, person.organization.keywords, person.organization.funding_events, person.organization.total_funding.
1b. Hunter Combined Enrichment ($0.01):
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"hunter","path":"/v2/combined/find","query":{"email":"{email}"}}'
Extract: data.person.first_name, data.person.last_name, data.person.linkedin_handle, data.person.title, data.company.name, data.company.domain, data.company.industry, data.company.description, data.company.headcount, data.company.technologies, data.company.twitter, data.company.category.
1c. Brand.dev Retrieve ($0.03 — CONDITIONAL: only if is_free_email == false):
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"brand-dev","path":"/v1/brand/retrieve","query":{"domain":"{domain}"}}'
Extract: title (company name), description, industries (including eic code), socials (twitter URL, github URL, linkedin URL), employeeCount, foundedYear, location.
SKIP this call if is_free_email == true — saves $0.03.
1d. Hunter Email Verifier ($0.01):
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"hunter","path":"/v2/email-verifier","query":{"email":"{email}"}}'
Extract: data.status (valid/invalid/accept_all/webmail/disposable/unknown), data.result (deliverable/undeliverable/risky).
PHASE 1 MERGE — Cross-Reference & Confidence
After all Phase 1 calls complete, merge data:
Person merge rules:
- Full name: prefer Apollo (structured), cross-ref with Hunter
- Title: prefer Apollo, cross-ref with Hunter
- LinkedIn URL: prefer Apollo
linkedin_url, fallback to Hunterlinkedin_handle(prependhttps://linkedin.com/in/) - Location: prefer Apollo (structured city/state/country)
- If Apollo and Hunter agree on name+title:
confidence = "high" - If only one source has data:
confidence = "medium" - If they disagree on name or title: flag conflict, keep both,
confidence = "low"
Company merge rules:
- Name: prefer Apollo org name, cross-ref with Hunter + Brand.dev
- LinkedIn URL: prefer Brand.dev socials, fallback Apollo
- Description: prefer Brand.dev (richer), fallback Hunter
- Employee count: prefer Apollo, cross-ref with Brand.dev + Hunter headcount
- Funding: use Apollo
funding_eventsandtotal_funding - Geo: prefer Apollo org location, cross-ref with Brand.dev
- Tech stack: use Hunter
technologies - Social URLs: use Brand.dev
socials(twitter, github)
AI/B2B Classification (zero extra cost):
Cross-reference three sources from Phase 1:
| Source | AI Signals | B2B Signals |
|---|---|---|
Brand.dev description + industries.eic | Parse description for: AI, ML, machine learning, deep learning, neural, LLM, GPT, NLP, computer vision | Parse for: SaaS, B2B, enterprise, platform, API, developer tools, infrastructure |
Apollo keywords[] + industry | Match keywords against AI terms | Match keywords against B2B terms |
Hunter category + company description | Check for AI/ML terms | Check for software/SaaS/B2B terms |
Confidence rules:
high: 2+ sources agreemedium: 1 source has signallow: weak inference only (e.g., "tech company" but no explicit AI/B2B terms)
PHASE 2 — Gap-Fill (conditional) — $0.00-$0.02
2a. Apollo Organization Enrich ($0.01 — ONLY if Apollo Phase 1 returned NO funding_events or funding data is empty):
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"apollo","path":"/api/v1/organizations/enrich","query":{"domain":"{domain}"}}'
Extract: organization.funding_events[], organization.total_funding, organization.latest_funding_stage, organization.latest_funding_amount, organization.estimated_num_employees, organization.annual_revenue.
2b. Tomba Enrich ($0.01 — ONLY if Apollo and Hunter disagree on person name OR title):
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"tomba","path":"/v1/enrich","query":{"email":"{email}"}}'
Use as tie-breaker. If Tomba agrees with Apollo: use Apollo data. If Tomba agrees with Hunter: use Hunter data. If all three disagree: keep Apollo as primary, flag conflict.
PHASE 3 — Sixtyfour Fallback (conditional, expensive) — $0.00-$0.20
3a. Sixtyfour Enrich Lead ($0.10 — ONLY if person NOT found after Phases 1-2, meaning no name AND no title AND no LinkedIn URL from any source):
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"sixtyfour","path":"/enrich-lead"}'
"lead_info": {
"email": "{email}",
"domain": "{domain}"
},
"struct": {
"full_name": "Full legal name of this person",
"title": "Current job title",
"linkedin_url": "LinkedIn profile URL (full URL)",
"city": "City",
"state": "State or region",
"country": "Country"
}
}'
3b. Sixtyfour Enrich Company ($0.10 — ONLY if company has major gaps AND org has >500 employees):
Major gaps = missing 2+ of: LinkedIn URL, description, employee count, funding data.
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"sixtyfour","path":"/enrich-company"}'
"target_company": {
"domain": "{domain}"
},
"struct": {
"company_name": "Official company name",
"description": "One-paragraph description",
"linkedin_url": "LinkedIn company page URL",
"employee_count": "Number of employees",
"total_funding_usd": "Total funding raised in USD",
"latest_funding_date": "Most recent funding round date",
"latest_funding_stage": "Most recent round stage",
"latest_funding_amount_usd": "Most recent round amount"
}
}'
PHASE 4 — Buying Signals (qualified leads only) — $0.00-$0.04
Gate: Only run Phase 4 if the company is:
- Funded (total_funding > 0) AND
- Classified as B2B (is_b2b_saas = true) AND
- Has >50 employees
4a. Brand.dev AI Products ($0.03 — extracts products, pricing tiers, and features from the website):
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"brand-dev","path":"/v1/brand/ai/products"}'
"domain": "{domain}"
}'
From the products response, extract buying signals:
- has_enterprise_plan: Check if any product has "enterprise" in name, tier, or target_audience
- has_self_serve: Check if any product has a listed price (self-serve) vs "Contact sales" pricing
- target_market: Infer from
target_audiencearrays across products
4b. Apollo Job Postings ($0.01 — ONLY if organization_id was captured from Phase 1):
curl -s -X POST $GOOSEWORKS_API_BASE/v1/proxy/orthogonal/run \
-H "Authorization: Bearer $GOOSEWORKS_API_KEY" \
-H "Content-Type: application/json" \
-d '{"api":"apollo","path":"/api/v1/organizations/{organization_id}/job_postings","query":{"organization_id":"{organization_id}"}}'
Search job postings for enterprise sales signals: titles containing "Enterprise", "Account Executive", "Solutions Engineer", "Sales Director", "Customer Success". If found, set hiring_enterprise_reps = true.
PHASE 5 — Cheap/Free Signals — $0.00-$0.01
5a. GitHub Stars (free — ONLY if Brand.dev socials or Apollo data returned a GitHub URL):
# Extract org name from GitHub URL, e.g., https://github.com/ngrok -> ngrok
# Use the GitHub public API (no auth needed for public repos):
curl -s "https://api.github.com/orgs/{org_name}/repos?sort=stars&per_page=5" | jq '[.[] | {name: .name, stars: .stargazers_count}]'
Sum the top repo stars or report the flagship repo star count.
5b. Twitter/X Followers (Scrape Creators — ONLY if a Twitter handle was found in Brand.dev socials or Apollo data):
provider: scrapecreators
method: GET
path: /v1/twitter/profile
query:
handle: "{twitter_handle}"
Extract: legacy.followers_count, legacy.friends_count, legacy.statuses_count, legacy.description.
FINAL — Compile & Output
Merge all phase results into the output format. Track which phases ran.
Output Format
Present the results as a JSON code block:
{
"person": {
"full_name": "string",
"title": "string",
"linkedin_url": "string",
"location": {"city": "string", "state": "string", "country": "string"},
"email_verified": "deliverable | undeliverable | risky | unknown",
"confidence": "high | medium | low",
"source": "apollo | hunter | sixtyfour | tomba | merged"
},
"company": {
"name": "string",
"domain": "string",
"linkedin_url": "string",
"description": "string",
"geo": {"city": "string", "state": "string", "country": "string"},
"employee_count": "number | null",
"founded_year": "number | null",
"funding": {
"total_amount": "number | null",
"total_amount_printed": "string | null",
"latest_round_date": "string | null",
"latest_round_stage": "string | null",
"latest_round_amount": "number | null",
"rounds": [{"date": "", "type": "", "amount": 0, "investors": ""}],
"confidence": "high | medium | low"
},
"classification": {
"is_ai": {"value": true, "confidence": "high", "evidence": ["Brand.dev description mentions ML", "Apollo keywords include 'artificial intelligence'"]},
"is_b2b_saas": {"value": true, "confidence": "high", "evidence": ["Hunter category: software", "Apollo industry: SaaS"]}
},
"buying_signals": {
"has_enterprise_plan": "boolean | null",
"has_self_serve": "boolean | null",
"hiring_enterprise_reps": "boolean | null",
"website_traffic_rank": "number | null",
"github_stars": "number | null",
"twitter_followers": "number | null",
"tech_stack": ["array | null"]
},
"confidence": "high | medium | low",
"source": "apollo | hunter | brand-dev | sixtyfour | merged"
},
"meta": {
"total_cost": "$0.XX",
"api_calls": [
{
"api": "apollo",
"endpoint": "/api/v1/people/match",
"status": "success",
"cost": "$0.01",
"latency_ms": 1200,
"fields_returned": ["name", "title", "linkedin_url", "organization"],
"fields_missing": [],
"error": null
}
],
"phases_run": [1, 2, 4, 5],
"enrichment_timestamp": "ISO datetime"
}
}
Error Visibility
Track EVERY API call in the meta.api_calls array with this structure:
{
"api": "string (apollo | hunter | brand-dev | sixtyfour | tomba | scrapecreators | github)",
"endpoint": "string",
"status": "success | partial | error | skipped",
"cost": "$0.XX",
"latency_ms": 0,
"fields_returned": [],
"fields_missing": [],
"error": "string | null"
}
Rules:
- If an API call fails, returns empty data, or times out: include it with
status='error'and a clear error message. Never silently skip failures. - If an API call was skipped due to gating logic (e.g., Brand.dev skipped for free email): include it with
status='skipped',cost='$0.00', and reason in error field (e.g., "Skipped: free email provider"). - If an API call returns partial data: use
status='partial', list what was returned and what was missing.
Cost Tracking
Sum all API call costs and report in meta.total_cost:
| API | Endpoint | Cost | When |
|---|---|---|---|
| Apollo | /api/v1/people/match | $0.01 | Always (Phase 1) |
| Hunter | /v2/combined/find | $0.01 | Always (Phase 1) |
| Brand.dev | /v1/brand/retrieve | $0.03 | Phase 1, skip for free email |
| Hunter | /v2/email-verifier | $0.01 | Always (Phase 1) |
| Apollo | /api/v1/organizations/enrich | $0.01 | Phase 2, only if funding missing |
| Tomba | /v1/enrich | $0.01 | Phase 2, only if person data conflicts |
| Sixtyfour | /enrich-lead | $0.10 | Phase 3, only if person not found |
| Sixtyfour | /enrich-company | $0.10 | Phase 3, only if major gaps + >500 employees |
| Brand.dev | /v1/brand/ai/products | $0.03 | Phase 4, only if funded + B2B + >50 employees |
| Apollo | /organizations/{id}/job_postings | $0.01 | Phase 4, only if org_id available |
| Scrape Creators | /v1/twitter/profile | ~$0.01 | Phase 5, only if Twitter handle found |
| GitHub API | public | $0.00 | Phase 5, only if GitHub URL found |
Example
Input: jane@acme.com
Expected flow:
- Domain:
acme.com,is_free_email = false - Phase 1 (parallel): Apollo people/match, Hunter combined, Brand.dev retrieve, Hunter email-verifier
- Phase 1 merge: Cross-reference person data, classify AI/B2B from descriptions+keywords
- Phase 2: Check if Apollo returned funding — if not, call Apollo org enrich. Check if person data conflicts — if so, call Tomba.
- Phase 3: Skip if person found and company data sufficient
- Phase 4: If company is funded + B2B + >50 employees, run Brand.dev AI products + Apollo job postings
- Phase 5: If GitHub URL found, grab star counts. If Twitter handle found, grab follower count via Scrape Creators
- Compile and output JSON
Tips
- Phase 1 calls should all fire simultaneously — they're independent
- Apollo's people/match is the single best-value call — it returns person AND embedded company data including funding events
- Brand.dev is the richest source for company description, industry classification, and social URLs — but costs 3x more than Apollo/Hunter, so skip it for free email providers
- The AI/B2B classification uses data already returned by Phase 1 — no extra API calls needed
- Hunter's
technologiesarray is the only source of tech stack data — valuable for technical buyers - Phase 3 (Sixtyfour) should be rare — Apollo + Hunter find most people. Only trigger for truly obscure leads
- Phase 4 buying signals are the most actionable data for GTM — but gate them to avoid wasting $0.04 on unqualified leads
- GitHub stars and Twitter followers are cheap/free social proof signals — always grab them if URLs/handles are available
Signals
- GitHub stars
- 1k
- Forks
- 206
- Last commit
- Sep 2026
Advanced
- Catalog kind
- skill
- Gateway key
gtm-enrichment-smart- Source
- github.com/gooseworks-ai/goose-skills