Connectors
/
Apollo
Live · 10 tools

Apollo Integration for AI Agents

The Apollo API is well-documented. Getting your agent to call it correctly — for real users, with per-scope OAuth registration, plan-gated endpoints, and credit-consuming enrichment — is the part that takes longer than it should.
Apollo
Live

Sales Intelligence

Prospecting

Status
Live
Tools
10 pre-built
Auth
OAuth 2.0
Credential storage
Sandbox support

OAuth 2.0

Auto token refresh

Revocation detection

BYOC required

The real problem

Why this is harder than it looks

Apollo has two entirely different auth systems that are easy to conflate. For personal use, you authenticate with an API key — generated in Settings, passed in a header, done in minutes. For agents acting on behalf of other Apollo users, you must implement OAuth 2.0 — a separate registration process that requires submitting your app through Apollo’s developer portal and waiting for approval before your OAuth credentials are issued. Developers often start with the API key path, build a working prototype, and only discover the OAuth requirement when they try to let real users connect their own Apollo accounts.

Once you’re in the OAuth path, Apollo’s scope model becomes the next friction point. There are ten distinct scopes, and they map directly to feature tiers: contacts_search, accounts_search, and person_read are restricted to paid plans. If a user on a free plan connects your agent and you call those endpoints, you get an error — not a permission warning at authorization time, but a runtime failure after the token is live. You need to know which scopes your agent actually needs before registration, because editing scopes after the fact requires users to go through the entire authorization flow again. Scope mismatches at setup mean re-authorization across your user base.

Then there’s the enrichment credit model. Calls to apollo_enrich_contact and apollo_enrich_account consume Apollo credits per successful match — and revealing personal emails or phone numbers deducts additional credits. An agent that enriches contacts aggressively can silently drain a user’s monthly credit allowance. This isn’t a token lifecycle problem; it’s a usage contract your agent logic has to respect. Per-user token isolation, token refresh, revocation detection, and the multi-tenant auth plumbing on top of all this add up quickly. Scalekit handles all of it. Your agent names a tool and passes parameters.

Capabilities

What your agent can do with Apollo

Once connected, your agent has 10 pre-built tools covering Apollo’s core prospecting and CRM workflow:

  • Search and enrich contacts: search your Apollo CRM with filters for title, seniority, location, and company; enrich any contact with verified emails and phone numbers using Apollo’s people-matching engine
  • Search and enrich accounts: search Apollo’s company database by industry, employee range, and location; enrich accounts with firmographic data including tech stack, funding rounds, and revenue estimates
  • Create and update CRM records: create contacts and accounts, update contact stage and properties as leads move through your pipeline
  • Retrieve individual records: fetch full contact or account profiles by ID with all available fields
  • List and discover sequences: browse available email sequences by name for outreach automation workflows
Setup context

What we're building

This guide connects a sales intelligence agent to Apollo — helping reps search prospects, enrich contacts, and manage CRM records without leaving your product.

🤖
Example agent
Sales intelligence assistant searching prospects, enriching contacts, and updating Apollo CRM on behalf of each rep
🔐
Auth model
B2B SaaS — each rep connects their own Apollo account. identifier = your user ID
⚙️
Scalekit account
app.scalekit.com — Client ID, Secret, Env URL
🔑
Apollo OAuth app
Register at developer.apollo.io — required for BYOC setup
Setup

1 Setup: One SDK, One credential

Install the Scalekit SDK. The only credential your application manages is the Scalekit API key — no Apollo secrets, no user tokens, nothing belonging to your customers.

pip install scalekit-sdk-python
import scalekit.client import os from dotenv import load_dotenv load_dotenv() scalekit = scalekit.client.ScalekitClient( client_id=os.getenv("SCALEKIT_CLIENT_ID"), client_secret=os.getenv("SCALEKIT_CLIENT_SECRET"), env_url=os.getenv("SCALEKIT_ENV_URL"), ) actions = scalekit.actions
import { ScalekitClient } from '@scalekit-sdk/node'; import 'dotenv/config'; const scalekit = new ScalekitClient( process.env.SCALEKIT_ENV_URL, process.env.SCALEKIT_CLIENT_ID, process.env.SCALEKIT_CLIENT_SECRET ); const actions = scalekit.actions;
Already have credentials?
Connected Accounts

2 Per-User Auth: Creating connected accounts

Each rep gets their own Connected Account, giving them a dedicated auth context. The identifier is any unique string from your system — a UUID, email, whatever you use internally.

response = actions.get_or_create_connected_account( connection_name="apollo", identifier="user_apo_123" # your internal user ID ) connected_account = response.connected_account print(f"Status: {connected_account.status}") # Status: PENDING — user hasn't authorized yet
const response = await actions.getOrCreateConnectedAccount({ connectionName: "apollo", identifier: "user_apo_123" // your internal user ID }); const connectedAccount = response.connectedAccount; console.log(`Status: ${connectedAccount.status}`); // Status: PENDING — user hasn't authorized yet

This call is idempotent — safe to call on every session start. Returns the existing account if one already exists.

Authorization Flow

3 The authorization flow

The rep authorizes your agent once. Scalekit generates the OAuth URL with correct scopes, redirect handling, and state pre-configured. After approval, you never see the token.

if connected_account.status != "ACTIVE": link = actions.get_authorization_link( connection_name="apollo", identifier="user_apo_123" ) # Redirect user → Apollo OAuth consent screen # Scalekit captures the token on callback return redirect(link.link)
if (connectedAccount.status !== "ACTIVE") { const { link } = await actions.getAuthorizationLink({ connectionName: "apollo", identifier: "user_apo_123" }); // Redirect user → Apollo OAuth consent screen // Scalekit captures the token on callback return redirect(link); }
Token management is automatic
After the user approves, Scalekit stores encrypted tokens and the connected account moves to ACTIVE. Access tokens refresh before expiry. If a rep revokes access from their Apollo account settings, the account moves to REVOKED — no silent failures. Check account.status before critical operations.
BYOC is required for Apollo
Apollo requires you to register your own OAuth application via the Apollo developer portal at developer.apollo.io and supply your own Client ID and Secret. Create your app, paste the Scalekit redirect URI as the callback URL, select your required scopes, then enter your credentials in the Scalekit dashboard. Token management stays fully handled after that one-time setup.
Calling Apollo

4 Calling Apollo: What your agent writes

With the connected account active, your agent calls Apollo actions using execute_tool. Name the tool, pass parameters. Scalekit handles token retrieval, request construction, and response parsing.

Search contacts

Search your Apollo CRM using filters for title, seniority, company, and location. Use keywords for full-text search across name, bio, and company fields.

result = actions.execute_tool( identifier="user_apo_123", tool_name="apollo_search_contacts", tool_input={ "title": "VP of Sales", "seniority": "vp", "company_name": "Acme Corp", "location": "San Francisco", "per_page": 25 } ) # Returns matching contacts with name, email, title, company, and LinkedIn URL
const result = await actions.executeTool({ identifier: "user_apo_123", toolName: "apollo_search_contacts", toolInput: { "title": "VP of Sales", "seniority": "vp", "company_name": "Acme Corp", "location": "San Francisco", "per_page": 25 } }); // Returns matching contacts with name, email, title, company, and LinkedIn URL

Enrich a contact

Retrieve a verified contact profile using an email or name + company. Each successful match consumes Apollo credits. Set reveal_phone_number only when needed — it deducts additional credits per match.

result = actions.execute_tool( identifier="user_apo_123", tool_name="apollo_enrich_contact", tool_input={ "email": "jane.smith@acmecorp.com", "reveal_phone_number": False } ) # Returns verified contact with employment history, social profiles, and matched fields
const result = await actions.executeTool({ identifier: "user_apo_123", toolName: "apollo_enrich_contact", toolInput: { "email": "jane.smith@acmecorp.com", "reveal_phone_number": false } }); // Returns verified contact with employment history, social profiles, and matched fields

Create a contact

Add a new contact to your Apollo CRM. first_name and last_name are required. Link to an existing account with account_id to keep your CRM organized.

result = actions.execute_tool( identifier="user_apo_123", tool_name="apollo_create_contact", tool_input={ "first_name": "Jane", "last_name": "Smith", "email": "jane.smith@acmecorp.com", "title": "VP of Sales", "organization_name": "Acme Corp", "linkedin_url": "https://linkedin.com/in/janesmith" } ) # Returns: { "id": "...", "first_name": "Jane", "last_name": "Smith", ... }
const result = await actions.executeTool({ identifier: "user_apo_123", toolName: "apollo_create_contact", toolInput: { "first_name": "Jane", "last_name": "Smith", "email": "jane.smith@acmecorp.com", "title": "VP of Sales", "organization_name": "Acme Corp", "linkedin_url": "https://linkedin.com/in/janesmith" } }); // Returns: { "id": "...", "first_name": "Jane", "last_name": "Smith", ... }

Enrich an account

Pull firmographic data for a company using its domain or name. Returns employee count, revenue estimates, tech stack, and funding rounds. Consumes Apollo credits per match.

result = actions.execute_tool( identifier="user_apo_123", tool_name="apollo_enrich_account", tool_input={ "domain": "acmecorp.com" } ) # Returns: employee count, revenue range, industry, tech stack, funding rounds, social profiles
const result = await actions.executeTool({ identifier: "user_apo_123", toolName: "apollo_enrich_account", toolInput: { "domain": "acmecorp.com" } }); // Returns: employee count, revenue range, industry, tech stack, funding rounds, social profiles
Framework wiring

5 Wiring into your agent framework

Scalekit integrates directly with LangChain. The agent decides what to call; Scalekit handles auth on every invocation. No token plumbing in your agent logic.

from langchain_anthropic import ChatAnthropic from langchain.agents import AgentExecutor, create_tool_calling_agent from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from scalekit.langchain import get_tools apollo_tools = get_tools( connection_name="apollo", identifier="user_apo_123" ) prompt = ChatPromptTemplate.from_messages([ ("system", "You are a sales intelligence assistant. Use the available tools to help research prospects, enrich contacts, and manage Apollo CRM records."), MessagesPlaceholder("chat_history", optional=True), ("human", "{input}"), MessagesPlaceholder("agent_scratchpad"), ]) agent = create_tool_calling_agent(ChatAnthropic(model="claude-sonnet-4-6"), apollo_tools, prompt) result = AgentExecutor(agent=agent, tools=apollo_tools).invoke({ "input": "Find VP-level contacts at fintech companies in New York with fewer than 500 employees and enrich the top 5 results" })
import { ChatAnthropic } from "@langchain/anthropic"; import { AgentExecutor, createToolCallingAgent } from "langchain/agents"; import { ChatPromptTemplate, MessagesPlaceholder } from "@langchain/core/prompts"; import { getTools } from "@scalekit-sdk/langchain"; const apolloTools = await getTools({ connectionName: "apollo", identifier: "user_apo_123" }); const prompt = ChatPromptTemplate.fromMessages([ ["system", "You are a sales intelligence assistant. Use the available tools to help research prospects, enrich contacts, and manage Apollo CRM records."], new MessagesPlaceholder("chat_history", true), ["human", "{input}"], new MessagesPlaceholder("agent_scratchpad"), ]); const agent = await createToolCallingAgent({ llm: new ChatAnthropic({ model: "claude-sonnet-4-6" }), tools: apolloTools, prompt }); const result = await AgentExecutor.fromAgentAndTools({ agent, tools: apolloTools, }).invoke({ input: "Find VP-level contacts at fintech companies in New York with fewer than 500 employees and enrich the top 5 results" });
Other frameworks supported
Tool reference

All 10 Apollo tools

Grouped by capability. Your agent calls tools by name — no API wrappers to write.

Contacts
apollo_search_contacts
Search contacts by title, seniority, company, location, industry, or keyword. Pagination supported. Requires paid plan.
apollo_enrich_contact
Enrich a contact profile using email or name + company via Apollo’s people-matching engine. Revealing personal emails or phone numbers consumes additional credits. Requires paid plan.
apollo_create_contact
Create a new contact in Apollo CRM with name (required), email, title, phone, LinkedIn URL, and account association
apollo_update_contact
Update any contact property by ID — name, email, title, phone, LinkedIn URL, or CRM stage. Only supplied fields are changed
apollo_get_contact
Retrieve a full contact profile by Apollo contact ID, including professional details, employment history, and social profiles
Accounts
apollo_search_accounts
Search Apollo’s company database by name, industry, employee range, revenue, location, or keyword. Requires paid plan.
apollo_enrich_account
Enrich a company record with firmographic data — employee count, revenue estimates, tech stack, funding rounds, and social profiles — using domain or company name. Consumes Apollo credits per match.
apollo_create_account
Create a new account (company) record in Apollo CRM with name (required), domain, phone, address, and LinkedIn URL
apollo_get_account
Retrieve a full company account profile by Apollo account ID, including firmographic data and social profiles
Sequences
apollo_list_sequences
List available email sequences (Apollo Sequences / Emailer Campaigns) with optional name filter and pagination. Returns sequence ID, name, status, and step count.
Connector notes

Apollo-specific behavior

Enrichment and search tools require a paid Apollo plan
apollo_enrich_contact, apollo_search_accounts, and apollo_search_contacts are restricted to paid Apollo plans. Calling these tools with a free-plan account returns an error at runtime — not at authorization time. Validate your users’ plan tier before exposing these tools in your agent.
Scope changes require full re-authorization
Apollo’s OAuth scopes are declared once at app registration. If you add new tool capabilities that require additional scopes after users have already authorized, those users must go through the full OAuth flow again. Plan your scope set carefully before shipping to production.
Enrichment consumes Apollo credits per match
Each call to apollo_enrich_contact or apollo_enrich_account deducts from the connected user’s Apollo credit balance. Revealing personal emails or direct phone numbers costs additional credits per successful match. Design your agent to enrich only when necessary — not speculatively on every contact in a search result.
Infrastructure decision

Why not build this yourself

The Apollo OAuth flow is documented. Token storage isn’t technically hard. But here’s what you’re actually signing up for:

PROBLEM 01
Apollo’s OAuth registration requires submitting your app for approval via the developer portal — with BYOC credentials required before any user can connect
PROBLEM 02
Scope selection is permanent at registration — adding new scopes later forces re-authorization across your entire user base, with no granular per-call override
PROBLEM 03
Per-user token isolation across a multi-tenant system — one rep’s Apollo credentials must never be accessible to another, even within the same sales team
PROBLEM 04
Revocation detection and graceful handling when users disconnect your app from their Apollo account — without silent failures continuing to attempt API calls on their behalf

That's one connector. Your agent product will eventually need Salesforce, HubSpot, Gmail, Slack, and whatever else your customers ask for. Each has its own OAuth quirks and failure modes.

Scalekit maintains every connector. You maintain none of them.

Ready to ship

Connect your agent to Apollo today

Free to start. Token management fully handled.
Apollo
Live

Sales Intelligence

Prospecting

Status
Live
Tools
10 pre-built
Auth
OAuth 2.0
Credential storage
Sandbox support