agentsclimarketplace

Instantly reference architecture

Skill jeremylongshore/claude-code-plugins-plus-skills/plugins/saas-packs/instantly-pack/skills/instantly-reference-architecture

'Implement Instantly.ai reference architecture with best-practice project layout.From its SKILL.md

Install
npx -y skills add jeremylongshore/claude-code-plugins-plus-skills --skill instantly-reference-architecture

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its file declares

Copied from the file, not written here

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

11.2 KB, ~2.4k tokens by cl100k_base, as published. Nobody here has run it

Instantly Reference Architecture

Overview

Reference architecture for production Instantly.ai integrations. Covers project layout, API client design, event-driven webhook processing, campaign management, lead pipeline, and analytics dashboard. Designed for teams building outreach automation on top of Instantly API v2.

Architecture Diagram

                                     Instantly API v2
                                    (api.instantly.ai)
                                          |
                    ┌─────────────────────┼─────────────────────┐
                    |                     |                     |
              Campaign Mgmt         Lead Pipeline         Account Mgmt
              (create/launch/       (import/move/          (warmup/
               pause/analytics)      enrich/block)         vitals/pause)
                    |                     |                     |
                    └─────────┬───────────┘                    |
                              |                                |
                    ┌─────────┴─────────┐                     |
                    |   Your Backend    |◄────────────────────┘
                    |  (Node/Python)    |
                    └────────┬──────────┘
                             |
                    ┌────────┴──────────┐
                    |  Webhook Receiver |◄──── Instantly Webhooks
                    |  (Cloud Run /     |      (reply_received,
                    |   Vercel / Fly)   |       email_bounced, etc.)
                    └────────┬──────────┘
                             |
               ┌─────────────┼─────────────┐
               |             |             |
           CRM Sync     Slack Alerts   Analytics DB

Project Layout

instantly-integration/
├── src/
│   ├── instantly/
│   │   ├── client.ts          # API client wrapper with retry + auth
│   │   ├── types.ts           # TypeScript interfaces for API schemas
│   │   ├── pagination.ts      # Cursor-based pagination helpers
│   │   └── cache.ts           # Analytics caching layer
│   ├── campaigns/
│   │   ├── create.ts          # Campaign creation with sequences
│   │   ├── launch.ts          # Campaign activation workflow
│   │   ├── analytics.ts       # Campaign performance tracking
│   │   └── templates.ts       # Email sequence templates
│   ├── leads/
│   │   ├── import.ts          # Lead import from CSV/CRM
│   │   ├── lists.ts           # Lead list management
│   │   ├── enrich.ts          # Lead enrichment pipeline
│   │   └── blocklist.ts       # Block list management
│   ├── accounts/
│   │   ├── warmup.ts          # Warmup enable/disable/monitor
│   │   ├── health.ts          # Account vitals testing
│   │   └── rotation.ts       # Account assignment to campaigns
│   ├── webhooks/
│   │   ├── server.ts          # Express webhook receiver
│   │   ├── handlers.ts        # Event type handlers
│   │   └── validation.ts     # Payload validation
│   └── config.ts              # Environment config
├── tests/
│   ├── unit/                  # Unit tests (mocked API)
│   ├── integration/           # Integration tests (mock server)
│   └── e2e/                   # End-to-end (live API, read-only)
├── scripts/
│   ├── seed-leads.ts          # Seed campaign with test leads
│   ├── audit.ts               # Workspace audit script
│   └── migrate-v1-to-v2.ts   # API migration helper
├── .env.example
├── .github/workflows/ci.yml
├── Dockerfile
├── package.json
└── tsconfig.json

Core Module Implementation

API Client (src/instantly/client.ts)

import "dotenv/config";

export class InstantlyClient {
  constructor(
    private apiKey = process.env.INSTANTLY_API_KEY!,
    private baseUrl = "https://api.instantly.ai/api/v2"
  ) {}

  async request<T>(path: string, init: RequestInit = {}): Promise<T> {
    const res = await fetch(`${this.baseUrl}${path}`, {
      ...init,
      headers: {
        "Content-Type": "application/json",
        Authorization: `Bearer ${this.apiKey}`,
        ...init.headers,
      },
    });

    if (res.status === 429) {
      await new Promise((r) => setTimeout(r, 2000));
      return this.request<T>(path, init);
    }

    if (!res.ok) {
      throw new InstantlyApiError(res.status, path, await res.text());
    }

    return res.json() as Promise<T>;
  }

  // Campaign operations
  campaigns = {
    list: (limit = 50) => this.request<Campaign[]>(`/campaigns?limit=${limit}`),
    get: (id: string) => this.request<Campaign>(`/campaigns/${id}`),
    create: (data: CreateCampaignInput) =>
      this.request<Campaign>("/campaigns", { method: "POST", body: JSON.stringify(data) }),
    activate: (id: string) =>
      this.request<void>(`/campaigns/${id}/activate`, { method: "POST" }),
    pause: (id: string) =>
      this.request<void>(`/campaigns/${id}/pause`, { method: "POST" }),
    analytics: (id: string) =>
      this.request<CampaignAnalytics>(`/campaigns/analytics?id=${id}`),
    analyticsDaily: (id: string, start: string, end: string) =>
      this.request(`/campaigns/analytics/daily?campaign_id=${id}&start_date=${start}&end_date=${end}`),
  };

  // Lead operations
  leads = {
    create: (data: CreateLeadInput) =>
      this.request<Lead>("/leads", { method: "POST", body: JSON.stringify(data) }),
    list: (filter: ListLeadsInput) =>
      this.request<Lead[]>("/leads/list", { method: "POST", body: JSON.stringify(filter) }),
    get: (id: string) => this.request<Lead>(`/leads/${id}`),
    delete: (id: string) => this.request(`/leads/${id}`, { method: "DELETE" }),
    updateInterest: (email: string, campaignId: string, value: number) =>
      this.request("/leads/update-interest-status", {
        method: "POST",
        body: JSON.stringify({ lead_email: email, campaign_id: campaignId, interest_value: value }),
      }),
  };

  // Account operations
  accounts = {
    list: (limit = 50) => this.request<Account[]>(`/accounts?limit=${limit}`),
    get: (email: string) => this.request<Account>(`/accounts/${encodeURIComponent(email)}`),
    enableWarmup: (emails: string[]) =>
      this.request("/accounts/warmup/enable", { method: "POST", body: JSON.stringify({ emails }) }),
    warmupAnalytics: (emails: string[]) =>
      this.request("/accounts/warmup-analytics", { method: "POST", body: JSON.stringify({ emails }) }),
    testVitals: (emails: string[]) =>
      this.request("/accounts/test/vitals", { method: "POST", body: JSON.stringify({ accounts: emails }) }),
    pause: (email: string) =>
      this.request(`/accounts/${encodeURIComponent(email)}/pause`, { method: "POST" }),
    resume: (email: string) =>
      this.request(`/accounts/${encodeURIComponent(email)}/resume`, { method: "POST" }),
  };

  // Webhook operations
  webhooks = {
    list: () => this.request<Webhook[]>("/webhooks?limit=50"),
    create: (data: CreateWebhookInput) =>
      this.request<Webhook>("/webhooks", { method: "POST", body: JSON.stringify(data) }),
    test: (id: string) => this.request(`/webhooks/${id}/test`, { method: "POST" }),
    delete: (id: string) => this.request(`/webhooks/${id}`, { method: "DELETE" }),
  };
}

Campaign Template System (src/campaigns/templates.ts)

export const SEQUENCE_TEMPLATES = {
  "3-step-cold": {
    name: "3-Step Cold Outreach",
    sequences: [{
      steps: [
        { type: "email" as const, delay: 0, variants: [
          { subject: "{{firstName}}, quick question about {{companyName}}", body: "..." },
        ]},
        { type: "email" as const, delay: 3, delay_unit: "days" as const, variants: [
          { subject: "Re: {{firstName}}, quick question", body: "..." },
        ]},
        { type: "email" as const, delay: 5, delay_unit: "days" as const, variants: [
          { subject: "Re: {{firstName}}, quick question", body: "..." },
        ]},
      ],
    }],
    defaults: {
      daily_limit: 50,
      stop_on_reply: true,
      email_gap: 120,
      link_tracking: false,
      open_tracking: true,
    },
  },

  "meeting-request": {
    name: "Meeting Request",
    sequences: [{
      steps: [
        { type: "email" as const, delay: 0, variants: [
          { subject: "15 min chat, {{firstName}}?", body: "..." },
        ]},
        { type: "email" as const, delay: 2, delay_unit: "days" as const, variants: [
          { subject: "Re: 15 min chat", body: "..." },
        ]},
      ],
    }],
    defaults: {
      daily_limit: 30,
      stop_on_reply: true,
      email_gap: 180,
    },
  },
};

Data Flow Summary

Lead CSV/CRM → import.ts → POST /leads → Campaign
                                            ↓
                              POST /campaigns/{id}/activate
                                            ↓
                              Instantly sends emails
                                            ↓
                              Webhook events fire
                                            ↓
                              handlers.ts routes events
                                            ↓
                    ┌─────────┬─────────┬───────────┐
                    CRM       Slack     Analytics   Block List

Error Handling

ErrorCauseSolution
Client constructor failsMissing INSTANTLY_API_KEYCheck .env file
Namespace methods failAPI scope mismatchVerify key has correct scopes
Import fails midwayNetwork/rate limitBatch with retry (see instantly-performance-tuning)
Webhook events missingWebhook not registeredRegister after deploy (see instantly-webhooks-events)

Resources

Next Steps

For multi-environment setup, see instantly-multi-env-setup.

What ships with it

Read from the repository

Just SKILL.md. No reference files, no scripts.

Keep looking

Skills are one crate of 325,949. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.