IN

instantly-upgrade-migration

Guides the migration of Instantly.ai applications from deprecated v1 endpoints to v2.

Install

mkdir -p .claude/skills/instantly-upgrade-migration && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/7119" && unzip -o skill.zip -d .claude/skills/instantly-upgrade-migration && rm skill.zip

Installs to .claude/skills/instantly-upgrade-migration

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Migrate Instantly.ai integrations from API v1 to v2.
52 charsno explicit “when” trigger
Advanced

Key capabilities

  • Audit existing Instantly API v1 calls in a codebase
  • Replace v1 query parameter authentication with v2 Bearer tokens
  • Update v1 endpoint paths to v2 REST-standard paths
  • Convert offset pagination to cursor-based pagination
  • Adjust request bodies to match v2 schemas
  • Add error handling for new v2 HTTP status codes

How it works

The skill outlines key changes between Instantly API v1 and v2, providing a migration map for authentication, endpoint paths, and request bodies, along with instructions to audit and adapt existing code.

Inputs & outputs

You give it
Instantly API v1 code, v1 API key, v2 API key
You get back
Updated code using Instantly API v2, with Bearer token authentication and new endpoint paths

When to use instantly-upgrade-migration

  • Upgrade Instantly SDK
  • Replace v1 query param auth with Bearer tokens
  • Migrate campaign endpoints
  • Update pagination logic

About this skill

Instantly Upgrade Migration: API v1 to v2

Overview

Migrate from Instantly API v1 (deprecated January 2026) to API v2. Key changes: Bearer token auth replaces query-string API keys, REST-standard endpoints replace legacy paths, scoped API keys replace single global key, and cursor-based pagination replaces offset pagination. Existing v1 integrations via Zapier/Make continue working, but new integrations must use v2.

Prerequisites

  • Existing Instantly API v1 integration
  • Access to Instantly dashboard to generate v2 API keys
  • Understanding of Bearer token authentication

Migration Map

Authentication Change

// v1: API key as query parameter
// DEPRECATED — do not use
const v1Url = `https://api.instantly.ai/api/v1/campaign/list?api_key=${API_KEY}`;

// v2: Bearer token in Authorization header
const v2Response = await fetch("https://api.instantly.ai/api/v2/campaigns", {
  headers: { Authorization: `Bearer ${API_KEY}` },
});

Endpoint Migration Table

Operationv1 Endpointv2 EndpointMethod Change
List campaignsGET /api/v1/campaign/listGET /api/v2/campaignsSame
Get campaignGET /api/v1/campaign/getGET /api/v2/campaigns/{id}Query -> Path param
Create campaignPOST /api/v1/campaign/createPOST /api/v2/campaignsREST standard
Launch campaignPOST /api/v1/campaign/launchPOST /api/v2/campaigns/{id}/activateNew path
Pause campaignPOST /api/v1/campaign/pausePOST /api/v2/campaigns/{id}/pauseNew path
Add leadsPOST /api/v1/lead/addPOST /api/v2/leadsSimplified
List leadsGET /api/v1/lead/listPOST /api/v2/leads/listGET -> POST
Delete leadsPOST /api/v1/lead/deleteDELETE /api/v2/leads/{id}REST standard
Get analyticsGET /api/v1/analytics/campaignGET /api/v2/campaigns/analyticsNew path
List accountsGET /api/v1/account/listGET /api/v2/accountsSimplified

Request Body Changes

// v1: Campaign creation
const v1Body = {
  api_key: "your-key",
  name: "Campaign Name",
  // Flat structure
};

// v2: Campaign creation — structured schedule and sequences
const v2Body = {
  name: "Campaign Name",
  campaign_schedule: {
    start_date: "2026-04-01",
    schedules: [{
      name: "Business Hours",
      timing: { from: "09:00", to: "17:00" },
      days: { "1": true, "2": true, "3": true, "4": true, "5": true, "0": false, "6": false },
      timezone: "America/New_York",
    }],
  },
  sequences: [{
    steps: [{
      type: "email",
      delay: 0,
      variants: [{ subject: "Hello {{firstName}}", body: "Hi {{firstName}}..." }],
    }],
  }],
};

Lead Operation Changes

// v1: Add leads to campaign
const v1AddLeads = {
  api_key: "your-key",
  campaign_id: "campaign-uuid",
  leads: [
    { email: "[email protected]", first_name: "Jane" },
  ],
};

// v2: Add leads individually (POST /api/v2/leads)
const v2AddLead = {
  campaign: "campaign-uuid",          // "campaign_id" -> "campaign"
  email: "[email protected]",
  first_name: "Jane",
  skip_if_in_workspace: true,         // New: deduplication control
  verify_leads_on_import: true,       // New: auto-verification
  custom_variables: { role: "CTO" },  // New: custom fields
};

// v2: Bulk operations use POST /api/v2/leads/move for batch moves

Instructions

Step 1: Audit Existing v1 Calls

set -euo pipefail
# Find all v1 API calls in your codebase
grep -rn "api/v1/" src/ --include="*.ts" --include="*.js" --include="*.py" || echo "No v1 calls found"
grep -rn "api_key=" src/ --include="*.ts" --include="*.js" --include="*.py" || echo "No query-string keys found"

Step 2: Create Migration Adapter

// src/instantly-migration.ts
// Drop-in adapter that maps v1 calls to v2 endpoints

export class InstantlyV1ToV2Adapter {
  private apiKey: string;
  private baseUrl = "https://api.instantly.ai/api/v2";

  constructor(apiKey: string) {
    this.apiKey = apiKey;
  }

  private async request<T>(path: string, options: RequestInit = {}): Promise<T> {
    const res = await fetch(`${this.baseUrl}${path}`, {
      ...options,
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${this.apiKey}`,
        ...options.headers,
      },
    });
    if (!res.ok) throw new Error(`Instantly ${res.status}: ${await res.text()}`);
    return res.json() as Promise<T>;
  }

  // v1: campaign/list -> v2: GET /campaigns
  async listCampaigns() {
    return this.request("/campaigns?limit=100");
  }

  // v1: campaign/get?campaign_id=X -> v2: GET /campaigns/{id}
  async getCampaign(campaignId: string) {
    return this.request(`/campaigns/${campaignId}`);
  }

  // v1: campaign/launch -> v2: POST /campaigns/{id}/activate
  async launchCampaign(campaignId: string) {
    return this.request(`/campaigns/${campaignId}/activate`, { method: "POST" });
  }

  // v1: campaign/pause -> v2: POST /campaigns/{id}/pause
  async pauseCampaign(campaignId: string) {
    return this.request(`/campaigns/${campaignId}/pause`, { method: "POST" });
  }

  // v1: lead/add (bulk) -> v2: POST /leads (one at a time)
  async addLeads(campaignId: string, leads: Array<{ email: string; first_name?: string }>) {
    const results = [];
    for (const lead of leads) {
      const result = await this.request("/leads", {
        method: "POST",
        body: JSON.stringify({
          campaign: campaignId,
          email: lead.email,
          first_name: lead.first_name,
          skip_if_in_workspace: true,
        }),
      });
      results.push(result);
    }
    return results;
  }

  // v1: analytics/campaign -> v2: GET /campaigns/analytics
  async getCampaignAnalytics(campaignId: string) {
    return this.request(`/campaigns/analytics?id=${campaignId}`);
  }
}

Step 3: Pagination Migration

// v1: Offset-based (skip/limit)
// const v1 = await fetch(`/api/v1/lead/list?api_key=${key}&campaign_id=${id}&skip=100&limit=50`);

// v2: Cursor-based (starting_after)
async function* paginateV2<T extends { id: string }>(
  path: string,
  pageSize = 100
): AsyncGenerator<T[]> {
  let startingAfter: string | undefined;
  while (true) {
    const qs = new URLSearchParams({ limit: String(pageSize) });
    if (startingAfter) qs.set("starting_after", startingAfter);
    const page = await instantly<T[]>(`${path}?${qs}`);
    if (page.length === 0) break;
    yield page;
    startingAfter = page[page.length - 1].id;
    if (page.length < pageSize) break;
  }
}

Step 4: New v2 Features to Adopt

// These features are v2-only — no v1 equivalent

// Scoped API keys
// POST /api/v2/api-keys — create keys with specific scopes
await instantly("/api-keys", {
  method: "POST",
  body: JSON.stringify({ name: "analytics-only", scopes: ["campaigns:read"] }),
});

// Subsequences (conditional follow-ups)
// POST /api/v2/subsequences
await instantly("/subsequences", {
  method: "POST",
  body: JSON.stringify({
    parent_campaign: campaignId,
    name: "Re-engage interested leads",
    conditions: { crm_status: [1] }, // triggered when lead is "Interested"
  }),
});

// Inbox placement testing
// POST /api/v2/inbox-placement-tests
await instantly("/inbox-placement-tests", {
  method: "POST",
  body: JSON.stringify({
    name: "Pre-launch deliverability test",
    email_subject: "Test Subject",
    email_body: "Test body content",
    type: 1,
  }),
});

// Block list management (bulk)
// POST /api/v2/block-lists-entries/bulk-create
await instantly("/block-lists-entries/bulk-create", {
  method: "POST",
  body: JSON.stringify({
    entries: ["competitor.com", "internal.com"],
  }),
});

Migration Checklist

  • Generate v2 API key with appropriate scopes
  • Replace api_key query params with Authorization: Bearer header
  • Update all endpoint paths per migration table above
  • Convert offset pagination to cursor-based pagination
  • Update request bodies (e.g., campaign_id -> campaign)
  • Add error handling for new HTTP status codes (422, 429)
  • Test all migrated endpoints against v2 mock server
  • Remove old v1 API key from environment

Error Handling

ErrorCauseSolution
401 on v2Using v1 key formatGenerate new v2 Bearer token
404 on v2 pathUsing v1 endpoint pathCheck migration table above
422 on lead addNew validation rules in v2Add required fields per v2 schema
Missing pagination dataUsing skip instead of starting_afterConvert to cursor pagination

Resources

Next Steps

For CI/CD integration, see instantly-ci-integration.

When not to use it

  • When only using Instantly API v2
  • When not migrating from Instantly API v1

Prerequisites

Existing Instantly API v1 integrationAccess to Instantly dashboard to generate v2 API keysUnderstanding of Bearer token authentication

Limitations

  • Existing v1 integrations via Zapier/Make continue working
  • New integrations must use v2
  • Requires generating new v2 API keys

How it compares

This approach provides a structured migration path from a deprecated API version to a newer one, unlike starting a new integration from scratch.

Compared to similar skills

instantly-upgrade-migration side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
instantly-upgrade-migration (this skill)127dReviewAdvanced
mistral-migration-deep-dive027dReviewAdvanced
apollo-upgrade-migration127dCautionIntermediate
exa-migration-deep-dive127dReviewIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

More by jeremylongshore

View all by jeremylongshore

analyzing-logs

jeremylongshore

Analyze application logs to detect performance issues, identify error patterns, and improve stability by extracting key insights.

14123

ollama-setup

jeremylongshore

Configure auto-configure Ollama when user needs local LLM deployment, free AI alternatives, or wants to eliminate hosted API costs. Trigger phrases: "install ollama", "local AI", "free LLM", "self-hosted AI", "replace OpenAI", "no API costs". Use when appropriate context detected. Trigger with relevant phrases based on skill purpose.

1167

backtesting-trading-strategies

jeremylongshore

Backtest crypto and traditional trading strategies against historical data. Calculates performance metrics (Sharpe, Sortino, max drawdown), generates equity curves, and optimizes strategy parameters. Use when user wants to test a trading strategy, validate signals, or compare approaches. Trigger with phrases like "backtest strategy", "test trading strategy", "historical performance", "simulate trades", "optimize parameters", or "validate signals".

1071

generating-database-seed-data

jeremylongshore

Process this skill enables AI assistant to generate realistic test data and database seed scripts for development and testing environments. it uses faker libraries to create realistic data, maintains relational integrity, and allows configurable data volumes. u... Use when working with databases or data models. Trigger with phrases like 'database', 'query', or 'schema'.

1033

cursor-codebase-indexing

jeremylongshore

Execute set up and optimize Cursor codebase indexing. Triggers on "cursor index setup", "codebase indexing", "index codebase", "cursor semantic search". Use when working with cursor codebase indexing functionality. Trigger with phrases like "cursor codebase indexing", "cursor indexing", "cursor".

885

testing-mobile-apps

jeremylongshore

Execute mobile app testing on iOS and Android devices/simulators. Use when performing specialized testing. Trigger with phrases like "test mobile app", "run iOS tests", or "validate Android functionality".

810

You might also like

mistral-migration-deep-dive

jeremylongshore

Execute Mistral AI major migrations and re-architecture strategies. Use when migrating to Mistral AI from another provider, performing major refactoring, or re-platforming existing AI integrations to Mistral AI. Trigger with phrases like "migrate to mistral", "mistral migration", "switch to mistral", "mistral replatform", "openai to mistral".

03

apollo-upgrade-migration

jeremylongshore

Plan and execute Apollo.io SDK upgrades. Use when upgrading Apollo API versions, migrating to new endpoints, or updating deprecated API usage. Trigger with phrases like "apollo upgrade", "apollo migration", "update apollo api", "apollo breaking changes", "apollo deprecation".

11

exa-migration-deep-dive

jeremylongshore

Execute Exa major re-architecture and migration strategies with strangler fig pattern. Use when migrating to or from Exa, performing major version upgrades, or re-platforming existing integrations to Exa. Trigger with phrases like "migrate exa", "exa migration", "switch to exa", "exa replatform", "exa upgrade major".

10

openrouter-upgrade-migration

jeremylongshore

Execute migrate and upgrade OpenRouter SDK versions safely. Use when updating dependencies or migrating configurations. Trigger with phrases like 'openrouter upgrade', 'openrouter migration', 'update openrouter', 'openrouter breaking changes'.

01

perplexity-upgrade-migration

jeremylongshore

Analyze, plan, and execute Perplexity SDK upgrades with breaking change detection. Use when upgrading Perplexity SDK versions, detecting deprecations, or migrating to new API versions. Trigger with phrases like "upgrade perplexity", "perplexity migration", "perplexity breaking changes", "update perplexity SDK", "analyze perplexity version".

10

aid-update-api

AndreVianna

>

00

Search skills

Search the agent skills registry