Apollo + Hunter Integration Hub

This is a merged hub covering two B2B contact enrichment vendors used in a cascade pattern: Apollo.io (organization-level enrichment, free tier) → Hunter.io (email finder fallback, 50-credit/month free tier). The cascade is implemented in il-marketplace-pull/scripts/enrich-contacts.js, which enriches InvestorLift wholesaler company records and writes results to the wholesaler_contacts table in Supabase (CCP project). Read this hub before modifying the enrichment pipeline, rotating API keys, or spending Hunter credits.

⚠️ SOURCE MISSING

Both KB directories are stub-only:

  • workspace/knowledge-base/apollo-io/ — contains only _audit file; no API.md, WEBHOOKS.md, or CREDENTIALS.md
  • workspace/knowledge-base/hunter-io/ — contains only _audit file; no API.md or CREDENTIALS.md

This hub is authored entirely from ~/.claude/skills/il-marketplace-pull/SKILL.md and the enrich-contacts.js script. Field names, rate limits, and endpoint paths are derived from the skill + script inspection, not from authoritative KB docs. Any deep API work should verify against live vendor docs at https://apolloio.github.io/apollo-api-docs/ and https://hunter.io/api-documentation/.


Apollo.io

Quick reference

FieldValue
VendorApollo.io
URLhttps://app.apollo.io
API Docshttps://apolloio.github.io/apollo-api-docs/
KB docSOURCE MISSING — workspace/knowledge-base/apollo-io/ is _audit stub only
Auth methodAPI key (Bearer or api_key param)
Auth credentialop://Aurora/apollo/api-key
Cred-proxy portpending (B1-B6 ratification per nemoclaw-audit-2026-05-03)
Webhook portn/a (outbound calls only)
Outbound API basehttps://api.apollo.io/v1
Rate limitsFree tier: ~50 org enrichments / day (NEEDS VERIFICATION — no KB doc)
Rate-limit action429 → skip account, log warning, continue to next; Discord ops if sustained
CostFree tier available; paid plans for higher volumes (NEEDS VERIFICATION)
Backup/recoveryVendor-owned; no local backup of raw Apollo responses
Statusproduction (free tier)

Organization enrichment endpoint

Used by enrich-contacts.js to find wholesaler company domain and LinkedIn URL:

POST /v1/organizations/enrich
Body: { "domain": "<company-domain>" }
      OR
      { "name": "<company-name>" }

Response keys used (NEEDS VERIFICATION against live response):
  organization.website_url     → company domain
  organization.linkedin_url    → company LinkedIn
  organization.name            → canonical company name

Fallback when Apollo returns nothing: enrich-contacts.js falls back to a heuristic domain: lowercase(company_name).replace(/\s+/g, '') + ".com". This is used only when Apollo has no record (small wholesalers not indexed).

Free tier constraint

Apollo’s free tier indexes primarily mid-market and enterprise companies. Small regional wholesalers (common in IL) may have no Apollo record. The cascade is designed for this: Apollo miss → Hunter email-finder with heuristic domain.


Hunter.io

Quick reference

FieldValue
VendorHunter.io
URLhttps://hunter.io
API Docshttps://hunter.io/api-documentation
KB docSOURCE MISSING — workspace/knowledge-base/hunter-io/ is _audit stub only
Auth methodAPI key (api_key query param)
Auth credentialop://Aurora/hunter/api-key
Cred-proxy portpending
Webhook portn/a (outbound calls only)
Outbound API basehttps://api.hunter.io/v2
Rate limitsFree tier: 50 credits/month — 1 credit per successful email-finder match
Rate-limit action429 → stop enrichment for current run; log remaining budget; do NOT exceed monthly cap
CostFree: 50 credits/month; Starter: 500 credits (99/mo)
Backup/recoveryVendor-owned
Statusproduction (free tier)

Email-finder endpoint

Used by enrich-contacts.js as the fallback step when Apollo provides a domain but no verified email:

GET /v2/email-finder
Params:
  domain=<company-domain>        (from Apollo enrichment or heuristic)
  first_name=<contact-first>     (if available from IL account data)
  last_name=<contact-last>       (if available)
  api_key=<from op://Aurora/hunter/api-key>

Response keys used (NEEDS VERIFICATION against live response):
  data.email         → dispositions manager email address
  data.score         → confidence score (0-100)
  data.sources[]     → provenance of email

Credit budget enforcement

The enrich-contacts.js --budget=<N> flag limits Hunter calls per run. Default budget: 50 (matches monthly free tier cap). Do NOT run enrichment without --budget — unrestricted runs can exhaust the month’s credits in a single pass on a large account list.

# Safe: respects monthly budget
node ~/.claude/skills/il-marketplace-pull/scripts/enrich-contacts.js --top=50 --budget=50
 
# Dangerous: no budget cap — do NOT run without explicit authorization
node ~/.claude/skills/il-marketplace-pull/scripts/enrich-contacts.js --top=200

Cascade flow

The cascade implements a priority ordering that maximizes enrichment quality while respecting Hunter’s 50-credit/month free tier ceiling.

For each unique account_id in acquisition_deals:
│
├─ Step 1: Apollo /v1/organizations/enrich
│   Input:  company_name from IL account data
│   Output: domain, linkedin_url, canonical_name
│   Cost:   FREE (Apollo free tier, ~50 orgs/day limit)
│   On hit: write domain + linkedin → wholesaler_contacts; continue to Step 2
│   On miss: heuristic domain (lowercase company.com); continue to Step 2
│
├─ Step 2: Hunter /v2/email-finder
│   Input:  domain (from Apollo or heuristic) + name fields if available
│   Output: dispositions manager email + confidence score
│   Cost:   1 Hunter credit per match
│   Budget: --budget flag (default 50 = monthly free tier ceiling)
│   On hit: write email + score → wholesaler_contacts
│   On miss: leave email NULL in wholesaler_contacts
│   On 429:  stop run; log remaining budget; alert Discord #ops
│
└─ Step 3: Write to wholesaler_contacts (Supabase CCP svueekfvfrvhylxygktb)
    Table:   wholesaler_contacts
    Key:     account_id (upsert — safe to re-run)
    Fields:  account_id, company_name, domain, linkedin_url, email,
             email_score, enriched_at, source (apollo | hunter | heuristic)

When to run

Recommended cadence: after each batch of new IL deals synced (post investorlift-daily-sync.sh), targeting only accounts not yet enriched (WHERE email IS NULL). Use --dry-run to audit before spending Hunter credits.

# Dry-run first
node ~/.claude/skills/il-marketplace-pull/scripts/enrich-contacts.js \
  --top=50 --budget=50 --dry-run
 
# Live run after dry-run looks clean
node ~/.claude/skills/il-marketplace-pull/scripts/enrich-contacts.js \
  --top=50 --budget=50

Components

  • ~/.claude/skills/il-marketplace-pull/scripts/enrich-contacts.js — cascade orchestrator (Apollo + Hunter)
  • ~/.claude/skills/il-marketplace-pull/scripts/account-rollup.js — analytics: top wholesalers by deal volume (read-only; no API calls)
  • ~/.claude/skills/il-marketplace-pull/SKILL.md — full skill spec including failure modes + triggers
  • workspace/knowledge-base/apollo-io/_audit — vendor audit stub (SOURCE MISSING: no API.md)
  • workspace/knowledge-base/hunter-io/_audit — vendor audit stub (SOURCE MISSING: no API.md)

How it’s used

  • Trigger: User says “enrich IL wholesaler contacts” / “find IL wholesaler emails” / “top IL wholesalers” — routes to /il-marketplace-pull skill
  • Workflow: enrich-contacts.js queries acquisition_deals for unique account_ids → Apollo → Hunter → upsert wholesaler_contacts → optional HubSpot contact create via hubspot-deal-ingest
  • Agents involved: _summary (consumes enriched contacts for outreach), _summary (data ops)
  • Failure mode 1: Hunter 429 — budget exhausted. Recovery: wait until next month’s credit reset; run with smaller --budget next time
  • Failure mode 2: Apollo returns nothing for small wholesalers — cascade continues with heuristic domain. Expected behavior, not an error.
  • Failure mode 3: wholesaler_contacts table missing — apply schema migration (HANDOFF-FOR-KIMI Phase 0). Error: relation "wholesaler_contacts" does not exist
  • Success criteria: wholesaler_contacts rows upserted with non-NULL email fields; email_score >= 70 for high-confidence matches; Hunter credits remaining > 0.

Agents that touch this

  • _summary — primary consumer; uses enriched emails for wholesaler outreach
  • _summary — data ops; runs enrichment cron and monitors Hunter credit budget

Skills that invoke this

Plans that govern this

Feedback rules

KB / source docs

System maps

  • agents-tier-structure — Acquisitions agent tier (consumer of enriched data)
  • integrations — external integrations topology showing Apollo+Hunter as enrichment layer

1password is the cluster anchor:

  • 1passwordop://Aurora/apollo/api-key + op://Aurora/hunter/api-key. Both keys live in 1Password vault Aurora. Access via op CLI: op read "op://Aurora/apollo/api-key". See reference_1password_op_access for op CLI auth pattern via OP_SERVICE_ACCOUNT_TOKEN.
  • All integration hubs that consume API keys are cluster members under the 1password anchor.

Apollo+Hunter feeds enriched contact data back into the real-estate pipeline:

  • investorlift — caller: provides account_id + company names that drive Apollo queries
  • supabase — destination: wholesaler_contacts table (CCP svueekfvfrvhylxygktb)
  • hubspot — downstream: enriched emails used to find/create HubSpot contacts in the acquisition pipeline

Open issues / TODOs

  • G-KB-SYNC-WITH-CLAUDEMD gap: Neither apollo-io nor hunter-io has a proper KB directory. Both are _audit stubs. Create API.md files + update CLAUDE.md platforms list.
  • Hunter credit monitoring: No automated check on remaining Hunter credits before enrichment runs. Risk: silent exhaustion. Wire a pre-run credit check (GET /v2/accountdata.requests.searches.used) and abort if budget < 5.
  • Apollo rate limit not confirmed: Free tier daily org-enrichment limit is NEEDS VERIFICATION. Run a test batch and monitor for 429s.
  • wholesaler_contacts schema migration: Confirm migration applied in CCP (table renamed from data_il_marketplace_contacts). Run SELECT table_name FROM information_schema.tables WHERE table_name = 'wholesaler_contacts' against CCP to verify.
  • Heuristic domain quality: Apollo-miss → company_name.toLowerCase().replace(/\s+/, '') + ".com" heuristic is low-quality for company names with punctuation or abbreviations. NEEDS VERIFICATION that Hunter accepts these without burning credits on zero-confidence results.
  • Credit tier upgrade: At IL enrichment scale (thousands of accounts), 50 free credits/month is a ceiling. Evaluate Hunter Starter ($49/mo, 500 credits) when enrichment volume warrants.

Recent activity

  • 2026-05-03: hub created (W2-S8 sub-agent); SOURCE MISSING flagged for both KB dirs; cascade flow documented from SKILL.md + enrich-contacts.js
  • 2026-04-28: enrich-contacts.js created as net-new il-marketplace-pull v2 piece (Apollo+Hunter cascade)
  • 2026-04-28: wholesaler_contacts table schema decision (renaming data_il_marketplace_contacts) per project_acquisition_deals_centralized_schema.md