Send and manage Resend emails, domains, contacts, templates, and audiences through one authenticated gateway.
Documents
instantly
Try itCall the Instantly API v2 with managed auth to handle cold email campaigns, leads, sending accounts, and analytics.
What it does
The skill proxies requests to api.instantly.ai via api.maton.ai, requiring only a MATON_API_KEY environment variable for authentication. It exposes endpoints for campaigns (list, create, activate, pause, delete, search by contact), leads (single and bulk add, list, move, delete), lead lists, sending accounts with warmup controls, the Unibox inbox (list, reply, forward, mark read, unread count), campaign analytics (overview, daily, per-step, warmup), block list entries, email verification, background job status, the current workspace, and custom tags. Multiple Instantly connections are switched via the Maton-Connection header, and all write operations require explicit user confirmation befor…
When to use it
- Create, activate, or pause outreach campaigns
- Bulk-add or move leads between campaigns
- Configure sending accounts and toggle warmup
- Pull campaign analytics (overview, daily, per-step, warmup)
The skill document
Instantly
Access the Instantly API v2 with managed authentication. Manage cold email campaigns, leads, sending accounts, and view analytics.
Quick Start
# List campaigns
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/instantly/api/v2/campaigns?limit=10')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Base URL
https://api.maton.ai/instantly/{native-api-path}
Maton proxies requests to api.instantly.ai and automatically injects your API key.
Authentication
All requests require the Maton API key in the Authorization header:
Authorization: Bearer $MATON_API_KEY
Environment Variable: Set your API key as MATON_API_KEY:
export MATON_API_KEY="YOUR_API_KEY"
Getting Your API Key
- Sign in or create an account at maton.ai
- Go to maton.ai/settings
- Copy your API key
Connection Management
Manage your Instantly connections at https://api.maton.ai.
List Connections
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections?app=instantly&status=ACTIVE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Create Connection
python <<'EOF'
import urllib.request, os, json
data = json.dumps({'app': 'instantly'}).encode()
req = urllib.request.Request('https://api.maton.ai/connections', data=data, method='POST')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Content-Type', 'application/json')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Get Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Response:
{
"connection": {
"connection_id": "{connection_id}",
"status": "ACTIVE",
"creation_time": "2026-02-11T22:19:35.798712Z",
"last_updated_time": "2026-02-11T22:20:15.702846Z",
"url": "https://connect.maton.ai/?session_token=...",
"app": "instantly",
"metadata": {}
}
}
Open the returned url in a browser to complete authorization.
Delete Connection
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections/{connection_id}', method='DELETE')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Specifying Connection
If you have multiple Instantly connections, specify which one to use with the Maton-Connection header:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/instantly/api/v2/campaigns')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
req.add_header('Maton-Connection', '{connection_id}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
If you have multiple connections, always include this header to ensure requests go to the intended account.
Security & Permissions
- Access is scoped to campaigns, leads, accounts, and email analytics within the connected Instantly account.
- All write operations require explicit user approval. Before executing any create, update, or delete call, confirm the target resource and intended effect with the user.
API Reference
Campaigns
List Campaigns
GET /instantly/api/v2/campaigns?limit=10&status=1&search=keyword
Query parameters:
limit- Number of results (default: 10)status- Campaign status filter (0=draft, 1=active, 2=paused, 3=completed)search- Search by campaign namestarting_after- Cursor for pagination
Get Campaign
GET /instantly/api/v2/campaigns/{campaign_id}
Create Campaign
POST /instantly/api/v2/campaigns
Content-Type: application/json
{
"name": "My Campaign",
"campaign_schedule": {
"schedules": [
{
"name": "My Schedule",
"timing": {
"from": "09:00",
"to": "17:00"
},
"days": {
"0": true,
"1": true,
"2": true,
"3": true,
"4": true
},
"timezone": "Etc/GMT+5"
}
]
}
}
Note: Timezone must use Etc/GMT format (e.g., "Etc/GMT+5", "Etc/GMT-8", "Etc/GMT+12").
#### Activate Campaign
```bash
POST /instantly/api/v2/campaigns/{campaign_id}/activate
Pause Campaign
POST /instantly/api/v2/campaigns/{campaign_id}/pause
Delete Campaign
DELETE /instantly/api/v2/campaigns/{campaign_id}
Search Campaigns by Lead Email
GET /instantly/api/v2/campaigns/search-by-contact?search=lead@example.com
Leads
Create Lead
POST /instantly/api/v2/leads
Content-Type: application/json
{
"campaign_id": "019bb3bd-9963-789e-b776-6c6927ef3f79",
"email": "lead@example.com",
"first_name": "John",
"last_name": "Doe",
"company_name": "Acme Inc",
"variables": {
"custom_field": "custom_value"
}
}
Bulk Add Leads
POST /instantly/api/v2/leads
Content-Type: application/json
{
"campaign_id": "019bb3bd-9963-789e-b776-6c6927ef3f79",
"leads": [
{
"email": "lead1@example.com",
"first_name": "John"
},
{
"email": "lead2@example.com",
"first_name": "Jane"
}
]
}
List Leads
Note: This is a POST endpoint due to complex filtering requirements.
POST /instantly/api/v2/leads/list
Content-Type: application/json
{
"campaign_id": "019bb3bd-9963-789e-b776-6c6927ef3f79",
"limit": 100
}
Get Lead
GET /instantly/api/v2/leads/{lead_id}
Delete Lead
DELETE /instantly/api/v2/leads/{lead_id}
Move Leads
POST /instantly/api/v2/leads/move
Content-Type: application/json
{
"lead_ids": ["lead_id_1", "lead_id_2"],
"to_campaign_id": "target_campaign_id"
}
Lead Lists
List Lead Lists
GET /instantly/api/v2/lead-lists?limit=10
Create Lead List
POST /instantly/api/v2/lead-lists
Content-Type: application/json
{
"name": "My Lead List"
}
Get Lead List
GET /instantly/api/v2/lead-lists/{list_id}
Update Lead List
PATCH /instantly/api/v2/lead-lists/{list_id}
Content-Type: application/json
{
"name": "Updated List Name"
}
Delete Lead List
DELETE /instantly/api/v2/lead-lists/{list_id}
Accounts (Sending Email Accounts)
List Accounts
GET /instantly/api/v2/accounts?limit=10
Get Account
GET /instantly/api/v2/accounts/{email}
Create Account
POST /instantly/api/v2/accounts
Content-Type: application/json
{
"email": "sender@example.com",
"first_name": "John",
"last_name": "Doe",
"provider_code": "google",
"smtp_host": "smtp.gmail.com",
"smtp_port": 587,
"smtp_username": "sender@example.com",
"smtp_password": "app_password",
"imap_host": "imap.gmail.com",
"imap_port": 993,
"imap_username": "sender@example.com",
"imap_password": "app_password"
}
Update Account
PATCH /instantly/api/v2/accounts/{email}
Content-Type: application/json
{
"first_name": "Jane"
}
Delete Account
DELETE /instantly/api/v2/accounts/{email}
Enable Warmup
POST /instantly/api/v2/accounts/warmup/enable
Content-Type: application/json
{
"emails": ["account1@example.com", "account2@example.com"]
}
Disable Warmup
POST /instantly/api/v2/accounts/warmup/disable
Content-Type: application/json
{
"emails": ["account1@example.com"]
}
Emails (Unibox)
List Emails
GET /instantly/api/v2/emails?limit=20
Get Email
GET /instantly/api/v2/emails/{email_id}
Reply to Email
POST /instantly/api/v2/emails/reply
Content-Type: application/json
{
"reply_to_uuid": "email_uuid",
"body": "Thank you for your response!"
}
Forward Email
POST /instantly/api/v2/emails/forward
Content-Type: application/json
{
"email_uuid": "email_uuid",
"to": "forward@example.com"
}
Mark Thread as Read
POST /instantly/api/v2/emails/threads/{thread_id}/mark-as-read
Get Unread Count
GET /instantly/api/v2/emails/unread/count
Update Email
PATCH /instantly/api/v2/emails/{email_id}
Content-Type: application/json
{
"is_read": true
}
Delete Email
DELETE /instantly/api/v2/emails/{email_id}
Analytics
Get Campaign Analytics
GET /instantly/api/v2/campaigns/analytics?id={campaign_id}
Query parameters:
id- Campaign ID (leave empty for all campaigns)start_date- Filter start date (YYYY-MM-DD)end_date- Filter end date (YYYY-MM-DD)exclude_total_leads_count- Set to true for faster response
Get Campaign Analytics Overview
GET /instantly/api/v2/campaigns/analytics/overview?id={campaign_id}
Get Daily Campaign Analytics
GET /instantly/api/v2/campaigns/analytics/daily?id={campaign_id}
Get Campaign Step Analytics
GET /instantly/api/v2/campaigns/analytics/steps?id={campaign_id}
Get Warmup Analytics
POST /instantly/api/v2/accounts/warmup/analytics
Content-Type: application/json
{
"emails": ["account@example.com"]
}
Block List
List Block List Entries
GET /instantly/api/v2/block-lists-entries?limit=100
Query parameters:
domains_only- Filter to domain entries onlysearch- Search entries
Create Block List Entry
POST /instantly/api/v2/block-lists-entries
Content-Type: application/json
{
"bl_value": "blocked@example.com"
}
Or block a domain:
POST /instantly/api/v2/block-lists-entries
Content-Type: application/json
{
"bl_value": "blockeddomain.com"
}
Delete Block List Entry
DELETE /instantly/api/v2/block-lists-entries/{entry_id}
Email Verification
Verify Email
GET /instantly/api/v2/email-verification/{email}
If verification takes longer than 10 seconds, status will be pending. Poll this endpoint to check status.
Response fields:
verification_status- Use this field (notstatus) to determine verification result
Background Jobs
Get Background Job Status
GET /instantly/api/v2/background-jobs/{job_id}
Query parameters:
data_fields- Comma-separated fields (e.g.,success_count,failed_count,total_to_process)
Workspace
Get Current Workspace
GET /instantly/api/v2/workspaces/current
Custom Tags
Toggle Tag on Resource
POST /instantly/api/v2/custom-tags/toggle-resource
Content-Type: application/json
{
"tag_id": "tag_uuid",
"resource_id": "campaign_or_account_id",
"resource_type": "campaign"
}
Pagination
Instantly uses cursor-based pagination with limit and starting_after:
GET /instantly/api/v2/campaigns?limit=10&starting_after=cursor_value
Response includes pagination info:
{
"items": [...],
"next_starting_after": "cursor_for_next_page"
}
Use next_starting_after value in the next request's starting_after parameter.
Code Examples
JavaScript
const response = await fetch(
'https://api.maton.ai/instantly/api/v2/campaigns?limit=10',
{
headers: {
'Authorization': `Bearer ${process.env.MATON_API_KEY}`
}
}
);
const data = await response.json();
Python
import os
import requests
response = requests.get(
'https://api.maton.ai/instantly/api/v2/campaigns',
headers={'Authorization': f'Bearer {os.environ["MATON_API_KEY"]}'},
params={'limit': 10}
)
data = response.json()
Notes
- Instantly API v2 uses snake_case for all field names
- Lead custom variables must be string, number, boolean, or null (no objects/arrays)
- The List Leads endpoint is POST (not GET) due to complex filtering requirements
- Campaign status values: 0=draft, 1=active, 2=paused, 3=completed
- Email verification may return
pendingstatus if it takes longer than 10 seconds - Warmup operations return background job IDs - poll the background jobs endpoint for status
- IMPORTANT: When using curl commands, use
curl -gwhen URLs contain brackets to disable glob parsing - IMPORTANT: When piping curl output to
jq, environment variables may not expand correctly. Use Python examples instead.
Error Handling
| Status | Meaning |
|---|---|
| 400 | Missing Instantly connection or invalid request |
| 401 | Invalid or missing Maton API key |
| 403 | Insufficient API key scopes |
| 429 | Rate limited |
| 4xx/5xx | Passthrough error from Instantly API |
Troubleshooting: API Key Issues
- Check that the
MATON_API_KEYenvironment variable is set:
echo $MATON_API_KEY
- Verify the API key is valid by listing connections:
python <<'EOF'
import urllib.request, os, json
req = urllib.request.Request('https://api.maton.ai/connections')
req.add_header('Authorization', f'Bearer {os.environ["MATON_API_KEY"]}')
print(json.dumps(json.load(urllib.request.urlopen(req)), indent=2))
EOF
Troubleshooting: Invalid App Name
- Ensure your URL path starts with
instantly. For example:
- Correct:
https://api.maton.ai/instantly/api/v2/campaigns - Incorrect:
https://api.maton.ai/api/v2/campaigns
Resources
Questions people ask
- How is authentication handled?
- A single MATON_API_KEY set as an environment variable authorizes every request; multiple Instantly accounts are switched by adding the Maton-Connection header.
- Are write operations executed automatically?
- No. The document states that all create, update, and delete calls require confirming the target resource and intended effect with the user first.
- What API surface is covered?
- Campaigns, leads, lead lists, sending accounts (with warmup), Unibox emails, campaign analytics, block list entries, email verification, background jobs, current workspace, and custom tags.
- How does pagination work?
- Instantly uses cursor-based pagination via the limit and starting_after query parameters; the next_starting_after field in the response feeds the next request.
Related skills
Call SendGrid v3 endpoints through managed OAuth to send email, manage contacts, templates, and senders.
Send emails and manage Mailgun domains, routes, templates, mailing lists, suppressions, and webhooks via managed OAuth.
Read and manage Mailchimp audiences, subscribers, campaigns, segments, and tags via an OAuth-handled API proxy.
Send WhatsApp Business messages, manage templates, and handle media via an OAuth-authenticated API proxy.
Query Google Ads campaigns, keywords, and metrics via GAQL with managed OAuth.