Diagnose and fix Instantly common errors and exceptions.
Use when encountering Instantly errors, debugging failed requests,
or troubleshooting integration issues.
Trigger with phrases like "instantly error", "fix instantly",
"instantly not working", "debug instantly".
Diagnostic reference for Instantly API v2 errors. Covers HTTP status codes, campaign state errors, account health issues, lead operation failures, and webhook delivery problems.
Prerequisites
Completed instantly-install-auth setup
Access to Instantly dashboard for verification
API key with appropriate scopes
HTTP Status Codes
Status
Meaning
Common Cause
Fix
400
Bad Request
Malformed JSON, invalid field values
Validate request body against schema
401
Unauthorized
Invalid, expired, or revoked API key
Regenerate key in Settings > Integrations
403
Forbidden
API key missing required scope
Create key with correct scope (e.g., campaigns:all)
404
Not Found
Invalid campaign/lead/account ID
Verify resource exists with a GET call first
422
Unprocessable Entity
Business logic violation (duplicate lead, invalid state)
Check error body for details
429
Too Many Requests
Rate limit exceeded
Implement exponential backoff (see below)
500
Internal Server Error
Instantly server issue
Retry with backoff; check status.instantly.ai
Campaign Errors
Campaign Won't Activate (Stuck in Draft)
// Diagnosis: check campaign requirements
async function diagnoseCampaign(campaignId: string) {
const campaign = await instantly<Campaign>(`/campaigns/${campaignId}`);
const issues: string[] = [];
// Check sequences
if (!campaign.sequences?.length || !campaign.sequences[0]?.steps?.length) {
issues.push("No email sequences — add at least one step with subject + body");
}
// Check schedule
if (!campaign.campaign_schedule?.schedules?.length) {
issues.push("No sending schedule — add schedule with timing and days");
}
// Check sending accounts
const mappings = await instantly(`/account-campaign-mappings/${campaignId}`);
if (!Array.isArray(mappings) || mappings.length === 0) {
issues.push("No sending accounts assigned — add via PATCH /campaigns/{id} with email_list");
}
// Check for leads
const leads = await instantly<Lead[]>("/leads/list", {
method: "POST",
body: JSON.stringify({ campaign: campaignId, limit: 1 }),
});
if (leads.length === 0) {
issues.push("No leads — add leads via POST /leads");
}
if (issues.length === 0) {
console.log("Campaign looks ready to activate");
} else {
console.log("Issues preventing activation:");
issues.forEach((i) => console.log(` - ${i}`));
}
}
Campaign Status Codes
Status
Label
Meaning
0
Draft
Not yet activated
1
Active
Currently sending
2
Paused
Manually paused
3
Completed
All leads processed
4
Running Subsequences
Main sequence done, subsequences active
-1
Accounts Unhealthy
Sending accounts have SMTP/IMAP errors
-2
Bounce Protect
Auto-paused due to high bounce rate
-99
Suspended
Account-level suspension
Fix: Accounts Unhealthy (-1)
async function fixUnhealthyAccounts(campaignId: string) {
// 1. Get accounts assigned to campaign
const accounts = await instantly<Account[]>("/accounts?limit=100");
// 2. Test vitals for each
const vitals = await instantly("/accounts/test/vitals", {
method: "POST",
body: JSON.stringify({ accounts: accounts.map((a) => a.email) }),
});
// 3. Identify and fix broken accounts
for (const v of vitals as any[]) {
if (v.smtp_status !== "ok" || v.imap_status !== "ok") {
console.log(`BROKEN: ${v.email} — SMTP=${v.smtp_status}, IMAP=${v.imap_status}`);
// Pause the broken account
await instantly(`/accounts/${encodeURIComponent(v.email)}/pause`, { method: "POST" });
console.log(` Paused ${v.email}. Fix credentials, then resume.`);
}
}
}
Lead Errors
Duplicate Lead (422)
// Prevent duplicates by setting skip flags
await instantly("/leads", {
method: "POST",
body: JSON.stringify({
campaign: campaignId,
email: "[email protected]",
first_name: "Jane",
skip_if_in_workspace: true, // skip if email exists anywhere in workspace
skip_if_in_campaign: true, // skip if already in this campaign
}),
});