Summary and recommendation
Apollo.io exposes a REST API at https://api.apollo.io/api/v1 supporting API key auth (header-only as of September 2024; query/body parameter passing is no longer supported) and OAuth 2.0 for approved partners. The API is oriented around CRM-style contact and account data-there is no REST endpoint to invite, update roles for, or deactivate seat users.
Seat user lifecycle is managed exclusively via SCIM (Organization plan, Okta or Entra ID only) or the Apollo UI. The Stitchflow MCP server with ~100 deep IT/identity integrations covers Apollo alongside the broader identity stack, removing the need to build and maintain polling or provisioning logic against Apollo's rate-limited endpoints.
API quick reference
| Has user API | Yes |
| Auth method | API Key (header) for direct customers; OAuth 2.0 Authorization Code for partners/integrations |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Organization (min. $119/user/month annual, min. 3 users); SSO must be configured first |
Authentication
Auth method: API Key (header) for direct customers; OAuth 2.0 Authorization Code for partners/integrations
Setup steps
- For API key auth: Log in to Apollo, navigate to Settings > Integrations, find the API option, and click Connect to generate a key.
- Pass the API key in the request header as 'X-Api-Key: YOUR_API_KEY'. As of September 2024, passing keys via query/body parameters is no longer supported.
- For endpoints requiring elevated access (e.g., Get a List of Users), toggle 'Set as master key' during key creation.
- For OAuth 2.0 (partners only): Register your app at Settings > Integrations > API > OAuth registration, providing app name, logo, redirect URL(s), and desired scopes.
- Once approved, redirect users to: https://app.apollo.io/#/oauth/authorize?client_id=
&redirect_uri= &response_type=code&scope= &state= - Exchange the returned authorization code for tokens via POST to https://app.apollo.io/api/v1/oauth/token with grant_type, client_id, client_secret, redirect_uri, and code.
- Store the access token (expires in 30 days) and refresh token securely; use the refresh token to obtain new access tokens.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| read_user_profile | Provides basic user profile info; added by default to all OAuth apps. | Identifying the Apollo user who owns an access token |
| app_scopes | Umbrella scope automatically added alongside all selected scopes in OAuth flows. | All OAuth-based integrations |
| contacts_search | Allows searching for contacts in the Apollo database. | People API Search, Search for Contacts |
| person_read | Allows reading person/contact records. | People Enrichment, contact read operations |
| opportunity_write | Allows creating and updating deal/opportunity records. | Create a Deal, Update a Deal |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| id | string | Unique Apollo user ID for the team member. | system-generated | immutable | Used as owner/assignee reference in Deals, Accounts, Tasks, and Sequences endpoints. |
| name | string | Full display name of the Apollo team member. | set at account creation | updatable via UI; not directly via a user-update REST endpoint | |
| string | Primary email address of the team member. | required | requires SCIM unassign/reassign to change; cannot be updated in-place via SCIM | Changing primary email via SCIM requires unassigning and re-assigning the user in the IdP. | |
| role | string | Permission profile assigned to the user (e.g., Admin, Billing and Seat Manager). | assigned at invite | managed via Apollo UI or SCIM IdP assignment | OAuth integrations require the authorizing user to hold Admin or Billing and Seat Manager role. |
| team_id | string | ID of the Apollo team the user belongs to. | optional | manageable via UI | Teams are used for analytics filtering; removing a user from a team does not delete them from Apollo. |
Core endpoints
List Users (Teammates)
- Method: GET
- URL:
https://api.apollo.io/api/v1/users - Watch out for: Requires a master API key. Scoped keys will return HTTP 403. User IDs returned here are used as owner references in other endpoints.
Request example
curl --request GET \
--url 'https://api.apollo.io/api/v1/users' \
--header 'X-Api-Key: YOUR_MASTER_API_KEY' \
--header 'Content-Type: application/json'
Response example
{
"users": [
{ "id": "abc123", "name": "Jane Doe", "email": "jane@example.com" }
]
}
View API Usage Stats and Rate Limits
- Method: POST
- URL:
https://api.apollo.io/api/v1/usage_stats/api_usage_stats - Watch out for: Requires a master API key. Returns per-endpoint limits per minute, hour, and day, which vary by plan.
Request example
curl --request POST \
--url 'https://api.apollo.io/api/v1/usage_stats/api_usage_stats' \
--header 'X-Api-Key: YOUR_MASTER_API_KEY' \
--header 'Content-Type: application/json'
Response example
{
"api_usage": [
{ "endpoint": "/api/v1/users", "limit_per_minute": 50,
"used_today": 12 }
]
}
People API Search
- Method: POST
- URL:
https://api.apollo.io/api/v1/mixed_people/api_search - Watch out for: Does not return email addresses or phone numbers. Does not consume credits. Requires master API key. Display limit is 50,000 records (100 per page, up to 500 pages).
Request example
curl --request POST \
--url 'https://api.apollo.io/api/v1/mixed_people/api_search' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{"per_page": 25, "page": 1}'
Response example
{
"people": [ { "id": "...", "first_name": "...",
"last_name": "..." } ],
"pagination": { "page": 1, "per_page": 25 }
}
Search for Contacts (in your account)
- Method: POST
- URL:
https://api.apollo.io/api/v1/contacts/search - Watch out for: Only returns contacts explicitly added to your team's Apollo account, not the broader Apollo database.
Request example
curl --request POST \
--url 'https://api.apollo.io/api/v1/contacts/search' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{"per_page": 25, "page": 1}'
Response example
{
"contacts": [ { "id": "...", "email": "...",
"name": "..." } ],
"pagination": { "page": 1, "per_page": 25 }
}
People Enrichment
- Method: POST
- URL:
https://api.apollo.io/api/v1/people/match - Watch out for: Consumes credits. Personal emails and phone numbers are not returned by default; use reveal_personal_emails and reveal_phone_number parameters explicitly.
Request example
curl --request POST \
--url 'https://api.apollo.io/api/v1/people/match' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{"email": "jane@example.com"}'
Response example
{
"person": { "id": "...", "first_name": "Jane",
"last_name": "Doe", "title": "...",
"organization_name": "..." }
}
Create a Contact
- Method: POST
- URL:
https://api.apollo.io/api/v1/contacts - Watch out for: Creates a contact in your Apollo account database, not a platform user/teammate. Use SCIM or the UI to provision actual seat users.
Request example
curl --request POST \
--url 'https://api.apollo.io/api/v1/contacts' \
--header 'X-Api-Key: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{"first_name":"Jane","last_name":"Doe","email":"jane@example.com"}'
Response example
{
"contact": { "id": "...", "first_name": "Jane",
"last_name": "Doe", "email": "jane@example.com" }
}
OAuth Token Exchange
- Method: POST
- URL:
https://app.apollo.io/api/v1/oauth/token - Watch out for: Access tokens expire after 30 days (2,592,000 seconds). Partners must register and be approved before using OAuth. Client secret is shown only once at generation.
Request example
curl --request POST \
--url 'https://app.apollo.io/api/v1/oauth/token' \
--data 'grant_type=authorization_code' \
--data 'client_id=YOUR_CLIENT_ID' \
--data 'client_secret=YOUR_CLIENT_SECRET' \
--data 'redirect_uri=YOUR_REDIRECT_URI' \
--data 'code=AUTH_CODE'
Response example
{
"access_token": "6vJtf0jt94...",
"token_type": "Bearer",
"expires_in": 2592000,
"refresh_token": "mVml3fp...",
"scope": "read_user_profile app_scopes"
}
Get User Profile (OAuth)
- Method: GET
- URL:
https://api.apollo.io/api/v1/auth/health - Watch out for: Used by OAuth partners to identify which Apollo user owns an access token. Requires Bearer token in Authorization header, not X-Api-Key.
Request example
curl --request GET \
--url 'https://api.apollo.io/api/v1/auth/health' \
--header 'Authorization: Bearer ACCESS_TOKEN' \
--header 'Content-Type: application/json'
Response example
{
"is_logged_in": true,
"user": { "id": "...", "email": "...",
"name": "..." }
}
Rate limits, pagination, and events
- Rate limits: Apollo uses a fixed-window rate limiting strategy. Each endpoint has distinct limits per minute, hour, and day. Limits vary by pricing plan. Exceeding limits returns HTTP 429.
- Rate-limit headers: Yes
- Retry-After header: No
- Rate-limit notes: Current rate limit usage and per-endpoint limits are returned in response headers of each API call. Use GET https://api.apollo.io/api/v1/usage_stats/api_usage_stats (master key required) to programmatically query all endpoint limits and current usage. Apollo does not publicly publish exact numeric limits per plan tier in documentation; consult the developer dashboard or response headers.
- Pagination method: offset
- Default page size: 25
- Max page size: 100
- Pagination pointer: page / per_page
| Plan | Limit | Concurrent |
|---|---|---|
| Free | Lower per-endpoint limits; exact values visible in Apollo developer dashboard and response headers | 0 |
| Basic / Professional | Higher per-endpoint limits than Free; exact values plan-specific and shown in response headers | 0 |
| Organization / Enterprise | Highest per-endpoint limits; exact values plan-specific and shown in response headers | 0 |
- Webhooks available: No
- Webhook notes: Apollo.io does not expose a native outbound webhook management API in its public REST API documentation. The waterfall enrichment endpoint delivers enriched data asynchronously to a caller-configured HTTPS webhook URL, but this is a one-way data delivery mechanism, not a general-purpose event subscription system. No official webhook event catalog or webhook registration endpoint is documented.
- Alternative event strategy: Use Apollo's Workflows feature (UI-based automation) or poll the relevant REST endpoints (e.g., contacts/search, usage_stats) on a schedule. For waterfall enrichment async delivery, configure a public HTTPS endpoint in your enrichment request payload.
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Organization (min. $119/user/month annual, min. 3 users); SSO must be configured first
Endpoint: Tenant URL is generated within Apollo at Settings > Integrations > Single Sign-On > [Provider] > User Auto Provisioning. The SCIM token is copied from the same location. Exact base URL is provider-specific and displayed in-app.
Supported operations: Create users (auto-provision on IdP assignment), Deactivate/deprovision users (on IdP unassignment), Update user attributes (synced from IdP)
Limitations:
- SSO must be fully configured before SCIM can be enabled.
- Supported IdPs are Okta and Microsoft Entra ID only; Google Workspace and OneLogin are not supported.
- Apollo supports users but not user groups during SSO/SCIM logins.
- Changing a user's primary email address requires unassigning and re-assigning the user in the IdP; in-place email updates are not supported.
- Apollo does not support custom SAML claim or attribute mapping.
- When SSO is enabled, all team members must log in exclusively via SSO; other login methods are blocked.
- SCIM provisioning requires admin access in both Apollo and the IdP.
Common scenarios
Three primary API scenarios are well-documented. First, enumerating seat users: GET https://api.apollo.io/api/v1/users with a master API key returns the users array with id, name, email, and role-scoped keys return HTTP 403.
User IDs from this endpoint serve as owner references in Deal, Account, and Task creation calls. Second, automated provisioning via SCIM 2.
0: requires the Organization plan with SSO pre-configured; navigate to Settings > Integrations > Single Sign-On > [Provider] > User Auto Provisioning to retrieve the SCIM token, then configure in Okta or Entra ID.
Apollo provisions and deprovisions on IdP assignment changes but does not support user groups or in-place email updates via SCIM.
Third, OAuth partner integrations: register at Settings > Integrations > API > OAuth registration, complete Apollo's approval process, then implement the authorization code flow with token refresh logic-access tokens expire after 30 days and the client secret is shown only once.
Enumerate all seat users (teammates) in an Apollo account
- Generate or obtain a master API key from Settings > Integrations > API > Connect.
- Call GET https://api.apollo.io/api/v1/users with header X-Api-Key: MASTER_KEY.
- Parse the returned 'users' array; each object contains the user's id, name, and email.
- Use the returned user IDs as owner/assignee values when creating Deals, Accounts, or Tasks via the API.
Watch out for: Only a master API key can access this endpoint. Scoped keys return HTTP 403. There is no REST endpoint to create, update roles for, or deactivate seat users; use SCIM or the UI for lifecycle management.
Automate seat user provisioning and deprovisioning via SCIM
- Ensure the account is on the Organization plan ($119/user/month annual, min. 3 users) and SSO is fully configured with Okta or Microsoft Entra ID.
- In Apollo, navigate to Settings > Integrations > Single Sign-On > [Provider] > User Auto Provisioning and copy the SCIM token.
- In your IdP (Okta or Entra ID), open the Apollo.io application, navigate to Provisioning settings, and enable API integration.
- Paste the SCIM token as the API credential and test the connection.
- Assign or unassign users/groups in the IdP; Apollo will automatically provision or deprovision the corresponding seat users.
- To change a user's primary email, unassign them in the IdP first, update the email, then reassign.
Watch out for: Apollo supports only individual users via SCIM, not user groups. Custom SAML attribute mapping is not supported. Once SSO is enabled, all users must log in exclusively via SSO.
Build a partner OAuth integration to act on behalf of Apollo users
- Register your app in Apollo at Settings > Integrations > API > OAuth registration; provide app name, logo, redirect URL(s), and required scopes. Await Apollo approval.
- Redirect the user to: https://app.apollo.io/#/oauth/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&response_type=code&scope=read_user_profile contacts_search&state=STATE
- After user authorization, receive the authorization code at your redirect URI.
- Exchange the code for tokens via POST to https://app.apollo.io/api/v1/oauth/token with grant_type=authorization_code, client_id, client_secret, redirect_uri, and code.
- Store the access_token (30-day expiry) and refresh_token securely.
- Use the access_token as a Bearer token in the Authorization header for subsequent API calls.
- Implement refresh token logic to exchange the refresh_token for a new access_token before expiry.
Watch out for: OAuth is for partners only and requires Apollo approval before use. The client secret is shown only once. Editing scopes after setup requires repeating the entire authorization flow. Only users with Admin or Billing and Seat Manager roles can authorize OAuth integrations.
Why building this yourself is a trap
Several non-obvious constraints create integration risk. Rate limits are per-endpoint and per-plan with separate minute, hour, and day windows; exact numeric limits are not published in documentation-check response headers or poll https://api.apollo.io/api/v1/usage_stats/api_usage_stats (master key required). People API Search caps at 50,000 records hard (100 per page, 500 pages max) regardless of filter breadth.
Enrichment endpoints consume credits synchronously, but waterfall enrichment delivers results asynchronously to a caller-supplied webhook URL-Apollo has no general-purpose webhook event subscription system. OAuth scope changes after initial setup require repeating the full authorization flow.
Any integration built against the contacts or accounts endpoints is operating on CRM data, not seat user data; conflating the two is a common source of provisioning failures.
Automate Apollo.io workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.