← all tools
Prospecting

Apollo

Find net-new people and companies, then reveal how to reach them.

Cost per callBYOK · vendor billed
Your own keyrequired
CategoryProspecting

Apollo is a prospecting database. Your agent searches it for people and companies matching your brief, then reveals emails and phone numbers only for the ones you shortlist. Searching is free. Revealing costs credits, so hyreflow filters first and spends second.

Apollo starts the pipeline. It builds the list, then hands the shortlist to enrichment for better coverage, or straight to a sequencer.

things you can ask for

  • Take this job brief url and build a first longlist, then clear every address with Enrichley
  • Find heads of engineering at Series B fintechs in Berlin and resolve whatever Apollo misses through FullEnrich
  • Pull the 40 companies hiring for this role, cross-check them against TheirStack, and give me the hiring manager on each
  • Load this shortlist into a paused Instantly campaign

works well with Apollo

  • TheirStack

    narrow to companies that are actually hiring before you spend a reveal

  • FullEnrich

    waterfall the contacts Apollo could not resolve on its own

  • Enrichley

    clear the addresses before a sequencer ever sees them

  • Instantly

    turn the finished list into a campaign, paused until you approve it

Skills that use Apollo

A skill is a whole pipeline your agent already knows. These ones call Apollo as part of the run.

signal5 steps

Layoff signal → poach displaced talent

Sweep Layoff Signal news, source displaced talent via GitHub + Apollo, enrich via Prospeo, push to outreach.

view skill →
signal5 steps

Funded round → 30-day talent sweep

PredictLeads signals fresh funding. Build a candidate pool via GitHub + Apollo weeks before the JDs go live.

coming soon
signal5 steps

Hiring sprint → competitor poach

TheirStack flags 50+ open roles. Poach displaced talent via Apollo + Lusha into Lemlist.

coming soon
compose5 steps

Candidate on the desk → 15-company spec campaign

Read the CV with claude, map who would actually want them via TheirStack + Apollo, name the hiring manager via Prospeo, send the anonymized profile through Instantly. Stops at the reply.

coming soon

What your agent reads before it touches Apollo

Every tool ships with a written playbook, and the agent loads it before the first call. Auth, rate limits, what each call costs, which actions need your approval, and the mistakes worth avoiding. It is the difference between an agent that knows the tool and one that guesses at it.

Read the Apollo docs →
Show the raw playbookwritten for the agent

Routing layer for Apollo API work. WHAT/guardrails here; HOW in reference/endpoints.md (59 ops) and the Python client lib/apollo.py. Full per-endpoint OpenAPI is cached at reference/docs/apollo/raw/<slug>.md.

1) Auth & config

  • Base URL: https://api.apollo.io/api/v1
  • Auth: API key in header x-api-key (Apollo → Settings → API). Env APOLLO_API_KEY; never hardcode.
  • Pagination: page + per_page; response pagination:{page,per_page,total_entries,total_pages} + a result array (people/contacts/accounts/organizations). Client _paginate follows it.

2) Credits & outreach guardrails (important)

  • Search ≠ Enrich. search_people / search_organizations are net-new prospecting — they return no emails/phones and cost no credits. Use them to build shortlists.
  • Enrichment costs credits. enrich_person (/people/match), bulk_enrich_people, enrich_organization reveal emails/phones and consume credits. reveal_personal_emails / reveal_phone_number flags gate paid reveals — default off, confirm before bulk.
  • Sequences = real outreach. add_contacts_to_sequence enrolls people into live sending and activate_sequence starts it — approval-gated (pilot one, confirm, then batch).
  • Pilot bulk enrichment/writes on 1 record first; show payload+response; get explicit go-ahead.

3) Operations covered by the client

People (search, enrich, bulk_enrich), organizations (search, enrich, bulk_enrich, get, job_postings), contacts (create, update, view, search, bulk_create), accounts (create, update, view, search), sequences (search, add_contacts, activate, deactivate), lookups (fields, email_accounts, users, lists). Anything else in the 59-op surface → generic request(method, path, …) + reference/endpoints.md.

4) Handoff with the GTM/recruiting layer

Apollo is a sourcing + enrichment engine. Canonical flow: search_people/search_organizations to build a net-new shortlist (free) → enrich_person only on the shortlist (credits) → write to your ATS (recruit-crm) or hand to a sequencer (instantly/sourcewhale). Enrich late, on the filtered set, never the whole funnel (over-provision then filter).

Field notes (production experience)

Field-shape note: these are vendor-native operational notes. The client returns the raw vendor JSON and uses the method names in this file — read field shapes accordingly (no normalized-wrapper / result.data. prefix).

Response shape (our direct client): people search returns top-level { total_entries, people, pagination } - read response["people"]. Company search is canonical at organizations (not accounts) - read response["organizations"]; rows carry name, primary_domain/domain, linkedin_url, industry.

  • Free vs paid people search: mixed_people/api_search = free preview (obfuscated names/contact gaps, no credits) - use for cheap discovery/shortlisting. mixed_people/search = paid (full coverage). Start free, escalate to paid only when needed.
  • Obfuscated last names: detect S****, K., -, N/A, masked strings from free search; do not feed them to email-finders/pattern generators. Bridge: free search -> people match by Apollo id -> use the resolved last_name. Flag last_name_obfuscated=true.
  • Company targeting: keep include_similar_titles=true unless strict matching is asked. Prefer q_organization_domains_list/organization_ids over name-only keywords. For exact industry use organization_industry_tag_ids (taxonomy IDs from industry_tag_id/industry_tag_hash in org rows - Apollo doesn't publish the taxonomy in the spec), not q_organization_keyword_tags (keyword search, pulls off-industry).
  • organization_num_employees_ranges is contract-sensitive - use the exact format Apollo expects; don't trust pagination.total_entries alone - pilot with low per_page first.

Callable surface — lib/apollo.py

Import: from lib.apollo import Apollo → instantiate Apollo() (reads key from env). Base: https://api.apollo.io/api/v1. Generic passthrough: request(method, path, *, params, json).

  • activate_sequence(sequence_id: str) -> dict — POST /emailer_campaigns/{id}/approve — starts the sequence sending.
  • add_contacts_to_sequence(sequence_id: str, contact_ids: list[str], email_account_id: str, **opts) -> dict — POST /emailer_campaigns/{id}/add_contact_ids — ENROLLS contacts into live outreach.
  • bulk_create_contacts(contacts: list[dict], **opts) -> dict
  • bulk_enrich_organizations(domains: list[str], **opts) -> dict — POST /organizations/bulk_enrich — up to 10 domains per call.
  • bulk_enrich_people(details: list[dict], **opts) -> dict — POST /people/bulk_match — enrich up to 10 people per call. Consumes credits.
  • create_account(payload: dict) -> dict
  • create_contact(payload: dict) -> dict — POST /contacts — create a CRM contact in your Apollo.
  • deactivate_sequence(sequence_id: str) -> dict
  • enrich_organization(domain: str, **params) -> dict — GET /organizations/enrich — enrich one company by domain.
  • enrich_person(payload: dict) -> dict — POST /people/match — enrich one person (email/phone). Consumes credits.
  • get_organization(org_id: str) -> dict
  • list_email_accounts(**params) -> Any — GET /email_accounts — sending mailboxes (need an id to enroll into sequences).
  • list_fields(**params) -> Any
  • list_lists(**params) -> Any — GET /labels — Apollo lists.
  • list_users(**params) -> Any
  • organization_job_postings(org_id: str, **params) -> Any
  • search_accounts(filters: dict | None = None) -> Iterator[dict]
  • search_contacts(filters: dict | None = None) -> Iterator[dict] — POST /contacts/search — search your Apollo contacts.
  • search_organizations(filters: dict | None = None) -> Iterator[dict] — POST /mixed_companies/search — company/account search.
  • search_people(filters: dict | None = None) -> Iterator[dict] — POST /mixed_people/api_search — prospect net-new people. No emails/phones, no credits.
  • search_sequences(filters: dict | None = None) -> Iterator[dict] — POST /emailer_campaigns/search.
  • update_account(account_id: str, payload: dict) -> dict
  • update_contact(contact_id: str, payload: dict) -> dict — PATCH /contacts/{contact_id}.
  • view_account(account_id: str) -> dict
  • view_contact(contact_id: str) -> dict