Instantly API Guide: Keys, Rate Limits, Leads and Campaigns
Instantly API v2: key and scopes, the 100 req/s rate limit, adding leads, creating and launching campaigns, sending accounts and webhooks, with curl examples.

On this page
Short answer: the Instantly API v2 lives at https://api.instantly.ai/api/v2. You authenticate with an API key in an Authorization: Bearer header; each key has scopes such as leads:create. Every Instantly plan includes API access (Growth $47, Hypergrowth $97, Light Speed $358 a month); webhooks start at Hypergrowth. The limit is 100 requests a second and 6,000 a minute for the whole workspace. API v1 was deprecated on January 19, 2026.
This guide covers the calls most cold email teams need: add sending accounts, turn on warmup, create a campaign, add leads, launch, read analytics and receive webhooks. Every endpoint, field and limit below comes from Instantly's own developer docs, read on 15 October 2026 and linked in each section. For the AI-assistant side of the same API, see Instantly MCP: setup, tools and limits.
Instantly API at a Glance
Instantly API v2 | Source | |
|---|---|---|
Base URL |
| |
Auth |
| |
Scopes | Per key, | |
Rate limit | 100 requests a second and 6,000 a minute per workspace, shared by v1, v2 and every key; 429 above it | |
Pagination |
| |
Plans | API on Growth, Hypergrowth and Light Speed; webhooks from Hypergrowth | |
Errors | JSON with | |
Spec | OpenAPI 3.1 at | |
v1 | Deprecated on January 19, 2026; v2 keys are separate from v1 keys |
Get an API Key
Open Settings, Integrations in Instantly (
app.instantly.ai/app/settings/integrations) and pick API Keys in the left sidebar.Click Create API Key, name it and select the scopes. A script that only adds leads needs
leads:create; a full setup script needs campaign and account scopes too.Copy the key. Instantly shows it once and cannot show it again (getting started).
Keep it in an environment variable and test it with a small read:
export INSTANTLY_API_KEY="your_key"
curl "https://api.instantly.ai/api/v2/campaigns?limit=10" \
-H "Authorization: Bearer $INSTANTLY_API_KEY"
A missing or wrong key answers 401. A key without the scope the endpoint needs is refused too, so give each script its own key with the smallest set of scopes.
Rate Limits and Pagination
Instantly counts requests per workspace: no more than 100 a second and 6,000 a minute, across v1, v2 and every key you created. Above either limit the request fails with 429. Instantly's own advice for large jobs is to send batches of 100 calls with a 2-second pause between batches (rate limit).
Two things keep the request count low. Use the bulk endpoints (up to 1,000 leads in one call), and page with a cursor: pass limit and the next_starting_after value from the previous page as starting_after.
Add Sending Accounts
POST /api/v2/accounts adds one sending account. The required fields are email, first_name, last_name, provider_code and the IMAP and SMTP username, password, host and port (create account). provider_code tells Instantly what the account is, and Instantly warns that a wrong code leaves the account unusable:
provider_code | Account type |
|---|---|
1 | Custom IMAP/SMTP |
2 | |
3 | Microsoft |
4 | AWS |
8 | AirMail |
11 | Airmail Instant |
For an SMTP/IMAP mailbox, such as one from Outreach2day, the call looks like this (host and ports are the ones every Outreach2day mailbox uses):
curl -X POST "https://api.instantly.ai/api/v2/accounts" \
-H "Authorization: Bearer $INSTANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"email": "anna@acmemail.com",
"first_name": "Anna",
"last_name": "Lee",
"provider_code": 1,
"imap_username": "anna@acmemail.com",
"imap_password": "MAILBOX_PASSWORD",
"imap_host": "outreachmailstream.com",
"imap_port": 993,
"smtp_username": "anna@acmemail.com",
"smtp_password": "MAILBOX_PASSWORD",
"smtp_host": "outreachmailstream.com",
"smtp_port": 465
}'
Google and Microsoft accounts connect through a separate OAuth flow that Instantly documents in its OAuth connection guide.
Turn On Warmup
POST /api/v2/accounts/warmup/enable takes up to 100 addresses in emails, or include_all_emails with up to 100 excluded_emails. It starts a background job; poll GET /api/v2/background-jobs/{id} for the result (enable warmup). POST /api/v2/accounts/warmup/disable turns it off.
curl -X POST "https://api.instantly.ai/api/v2/accounts/warmup/enable" \
-H "Authorization: Bearer $INSTANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"emails": ["anna@acmemail.com", "ben@acmemail.com"]}'
Mailboxes exported from Outreach2day already warm up in Outreach2day, and that warmup keeps running after the export, so Instantly's warmup is optional for them.
Create a Campaign
POST /api/v2/campaigns needs name and campaign_schedule. The schedule needs at least one entry in schedules, each with name, timing (from and to as HH:MM), days (boolean keys "0" to "6"; the reference does not say which number is Monday, so check the schedule in the app after the first call) and a timezone from Instantly's list (create campaign).
The email copy goes in sequences. It is an array, but Instantly reads only the first element, so put every step into sequences[0].steps. Each step needs type ("email"), delay (in days unless delay_unit says minutes or hours) and at least one variant with subject and body. email_list picks the sending accounts. A campaign with two steps, built from those fields:
curl -X POST "https://api.instantly.ai/api/v2/campaigns" \
-H "Authorization: Bearer $INSTANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Q4 SaaS founders",
"campaign_schedule": {
"schedules": [{
"name": "Main schedule",
"timing": {"from": "09:00", "to": "17:00"},
"days": {"1": true, "2": true, "3": true,
"4": true, "5": true},
"timezone": "America/Chicago"
}]
},
"sequences": [{
"steps": [
{"type": "email", "delay": 3, "variants": [{
"subject": "Quick question",
"body": "Hi there,<br/><br/>..."
}]},
{"type": "email", "delay": 4, "variants": [{
"subject": "",
"body": "Following up on my note.<br/>..."
}]}
]
}],
"email_list": ["anna@acmemail.com", "ben@acmemail.com"],
"daily_limit": 50,
"stop_on_reply": true
}'
The response returns the campaign with its id. Start it with POST /api/v2/campaigns/{id}/activate and stop it with POST /api/v2/campaigns/{id}/pause (activate).
Add Leads
POST /api/v2/leads/add adds up to 1,000 leads in one request, to a campaign (campaign_id) or to a list (list_id); a call takes one of the two. With campaign_id every lead needs an email. skip_if_in_workspace, skip_if_in_campaign and skip_if_in_list drop duplicates, and verify_leads_on_import checks the addresses on the way in (add leads in bulk).
curl -X POST "https://api.instantly.ai/api/v2/leads/add" \
-H "Authorization: Bearer $INSTANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"campaign_id": "CAMPAIGN_ID",
"skip_if_in_workspace": true,
"leads": [
{"email": "john@example.com", "first_name": "John",
"company_name": "Example Inc.",
"custom_variables": {"industry": "SaaS"}}
]
}'
For a single lead, POST /api/v2/leads takes the same fields with campaign for the campaign id (create lead). POST /api/v2/leads/list searches leads; it is a POST because the filters are complex.
The same upload in Python, in chunks of 1,000 with a pause on 429:
import os, time, requests
KEY = os.environ["INSTANTLY_API_KEY"]
URL = "https://api.instantly.ai/api/v2/leads/add"
def add_leads(campaign_id, leads):
for i in range(0, len(leads), 1000):
body = {"campaign_id": campaign_id,
"skip_if_in_workspace": True,
"leads": leads[i:i + 1000]}
while True:
r = requests.post(URL, json=body, timeout=60,
headers={"Authorization": f"Bearer {KEY}"})
if r.status_code != 429:
break
time.sleep(2)
r.raise_for_status()
Read Analytics
GET /api/v2/campaigns/analytics returns campaign analytics; pass id for one campaign or leave it out for all, and narrow the dates with start_date and end_date (campaign analytics). There are overview, daily and per-step variants as well.
curl "https://api.instantly.ai/api/v2/campaigns/analytics?id=CAMPAIGN_ID&start_date=2026-10-01" \
-H "Authorization: Bearer $INSTANTLY_API_KEY"
Free guide19 min read
Send 100,000 cold emails a month
Domains and mailboxes you need, DNS, warmup, lists, copy and follow-ups, with a launch checklist, sent to your inbox.
Webhooks
POST /api/v2/webhooks needs only target_hook_url; event_type picks one event or all_events, and campaign limits it to one campaign (create webhook). Events include email_sent, email_opened, email_link_clicked, reply_received, email_bounced, lead_unsubscribed, campaign_completed, account_error and the lead status events such as lead_interested and lead_meeting_booked. GET /api/v2/webhooks/event-types lists them. Webhooks need the Hypergrowth plan or above.
curl -X POST "https://api.instantly.ai/api/v2/webhooks" \
-H "Authorization: Bearer $INSTANTLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{"target_hook_url": "https://example.com/hooks/instantly",
"event_type": "reply_received"}'
Each payload carries timestamp, event_type, workspace, campaign_id and campaign_name, plus lead and email fields where they apply. Instantly's webhook guide spells the click event link_clicked while the API list says email_link_clicked; match on the value you receive (webhook events).
Connect Outreach2day Mailboxes With the API Key
You do not need to call POST /api/v2/accounts for mailboxes you buy from Outreach2day. Paste your Instantly API key once in the Outreach2day app (Export to sequencer) and export the mailboxes in one click: Outreach2day creates each one in Instantly as a custom IMAP/SMTP account (provider code 1) with its logins, adds new mailboxes as they are created and, with auto reconnect on, reconnects ones that drop. The field-by-field setup inside Instantly is on the Instantly integration page, and the same export through our REST API is in add email accounts to Instantly or Smartlead via API.
Outreach2day mailboxes cost $2.50 a month each (12 minimum), with warmup and a sending engine included, set up in about 12 minutes on your own domains. Teams that want one product can also send from Outreach2day's own campaigns; for 1,000 mailboxes and more, the volume price is set on a call. Other routes in: the cold email API for domains, mailboxes and warmup, and the Smartlead API guide if you send from Smartlead.
Instantly API From an AI Assistant
Instantly's MCP server at https://mcp.instantly.ai/mcp turns the same V2 API into tools for Claude, Cursor and other MCP clients, with the same key. Setup per client, the tool list and its limits are on Instantly MCP: setup, tools and limits.
FAQ
Is the Instantly API free?
There is no separate API fee. Instantly's pricing page lists API access on every plan from Growth at $47 a month; webhooks need Hypergrowth ($97) or above.
What is the Instantly API rate limit?
100 requests a second and 6,000 a minute, for the whole workspace and shared by every key and by API v1 and v2. Requests over the limit get 429.
Can I still use Instantly API v1?
Instantly deprecated v1 on January 19, 2026, and v1 keys do not work with v2. Its migration guide says Zapier and Make integrations built on v1 keep working.
How many leads can I add in one request?
Up to 1,000 with POST /api/v2/leads/add, into one campaign or one list.
How do I add many sending accounts at once?
The API adds one account per POST /api/v2/accounts call. For mailboxes from Outreach2day, the export with your Instantly API key adds them all in one click and keeps new ones in sync.
Get Started
Create an Outreach2day account, order mailboxes on your domains and connect Instantly with its API key; the mailboxes arrive in Instantly warm.
Keep reading
Send 100,000 cold emails a month
How to send 100,000 cold emails a month while keeping quality, engagement and conversion rates high: domains, mailboxes, warmup, leads, copy and scaling
Step-by-step playbook · 19 min readEmail tools9 min read
Smartlead API Guide: Keys, Rate Limits, Campaigns and Leads
Email tools11 min read
Instantly Pricing 2026: Plans, Add-Ons and Real Cost
Email tools8 min read
Instantly and Smartlead MCP Servers for Claude
Answer2 min read
Should I Send Cold Email to Personal Gmail Addresses?
Agent skill
Cold email lead list cleaner