ActiveCampaign Connector Guide

The ActiveCampaign connector helps Tealfabric workflows create, update, and retrieve marketing records such as contacts, list memberships, and campaign-related data. This guide explains how to configure the connector, apply practical request patterns, and keep automation reliable as your marketing operations scale.

Document information
FieldValue
Canonical URL/docs/04_connecting-systems/connectors/a/activecampaign
Version (published date)2026-05-08
Tagsconnectors, reference, activecampaign
Connector IDactivecampaign-1.0.0

ActiveCampaign connector flow showing secure API key configuration, contact lifecycle updates, and list membership synchronization from Tealfabric workflows.

When to use this connector

Use this connector when your workflows need to sync leads from forms, enrich contact profiles from internal systems, or maintain list membership based on product or billing events. It is especially effective when marketing automation should stay coordinated with operational data generated outside ActiveCampaign. A consistent identifier strategy for email and contact IDs keeps downstream automations more predictable.

Prerequisites

Before configuring the integration, confirm your ActiveCampaign account API URL and API key in the ActiveCampaign developer settings. Decide which objects your workflow will own, such as contacts and list assignments, and ensure the key has permission for those operations. Early scope alignment reduces data drift and accidental duplicate records.

Configuration reference

Connector credentials and defaults are stored in integration configuration and reused during execution. Keep secrets out of logs and rotate keys through your normal credential policy.

  • api_key (required for test): API token sent as the Api-Token header.
  • base_url (optional): Base API URL for your account, typically ending in /api/3 or /v3.
  • account_name (optional): Account slug used when constructing account-specific API URLs.
  • api_region (optional): Region identifier for account-specific domain patterns (defaults to us).
  • api_secret (optional): Reserved for future use; not sent by the connector today.
  • timeout_seconds (optional): Timeout for connector requests (default 30).

The test operation validates that api_key is configured and calls GET accounts. Other operations (send, receive, sync, batch) do not preflight-validate configuration; missing credentials surface as ActiveCampaign API authentication errors. On config failure, test returns Configuration validation failed.

Create or update contacts

The send operation is the main write path and is commonly used to create contacts and keep key fields up to date. The examples below follow the same behavior across languages so teams can compare and reuse patterns safely.

const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";

type ContactResult = {
  contact?: { id?: string; email?: string; firstName?: string; lastName?: string };
};

async function createActiveCampaignContact(
  integrationId: string,
  email: string
): Promise<ContactResult> {
  const response = await fetch(
    `${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`,
    {
      method: "POST",
      headers: {
        "X-API-Key": apiKey,
        "X-Tenant-ID": tenantId,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        operation: "send",
        endpoint: "contacts",
        method: "POST",
        data: {
          contact: {
            email,
            firstName: "Jordan",
            lastName: "Lee",
            phone: "+1-555-0100",
          },
        },
      }),
    }
  );

  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
  const payload = (await response.json()) as {
    success?: boolean;
    data?: { data?: ContactResult; response?: ContactResult; message_count?: number };
  };
  if (!payload.data?.data) throw new Error("Missing contact payload");
  return payload.data.data;
}
curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
  -H "X-API-Key: <API_KEY>" \
  -H "X-Tenant-ID: <TENANT_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "send",
    "endpoint": "contacts",
    "method": "POST",
    "data": {
      "contact": {
        "email": "jordan.lee@example.com",
        "firstName": "Jordan",
        "lastName": "Lee"
      }
    }
  }'
{
  "success": true,
  "data": {
    "message_count": 1,
    "data": {
      "contact": {
        "id": "<ENTITY_ID>",
        "email": "jordan.lee@example.com",
        "firstName": "Jordan",
        "lastName": "Lee"
      }
    },
    "response": {
      "contact": {
        "id": "<ENTITY_ID>",
        "email": "jordan.lee@example.com",
        "firstName": "Jordan",
        "lastName": "Lee"
      }
    }
  }
}

Retrieve contacts and segment-ready data

Use the receive operation to list contacts, search by email, or pull records for downstream segmentation workflows. Pagination and filtering are important when datasets grow, so include limit and offset or search parameters in repeatable runs.

const baseUrl = "https://api.example.com/api/v1";
const tenantId = "<TENANT_ID>";
const apiKey = "<API_KEY>";

type ContactRecord = { id?: string; email?: string; firstName?: string; lastName?: string };

async function listActiveCampaignContacts(integrationId: string): Promise<ContactRecord[]> {
  const response = await fetch(
    `${baseUrl}/integrations/${encodeURIComponent(integrationId)}/execute`,
    {
      method: "POST",
      headers: {
        "X-API-Key": apiKey,
        "X-Tenant-ID": tenantId,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({
        operation: "receive",
        endpoint: "contacts",
        query: {
          limit: 20,
          offset: 0,
          search: "example.com",
        },
      }),
    }
  );

  if (!response.ok) throw new Error(`Request failed: ${response.status}`);
  const payload = (await response.json()) as {
    success?: boolean;
    data?: { data?: ContactRecord[]; message_count?: number; total_size?: number };
  };
  if (!payload.data?.data) throw new Error("Missing contacts payload");
  return payload.data.data;
}
{
  "success": true,
  "data": {
    "message_count": 2,
    "data": [
      { "id": "1", "email": "jordan.lee@example.com" },
      { "id": "2", "email": "sam.park@example.com" }
    ],
    "total_size": 2
  }
}

Validate integration health and reliability

Run the test operation whenever you rotate API keys or update account-level API settings. Most failures come from invalid credentials, incorrect base URL configuration, or bursty request patterns that trigger throttling. The connector applies local rate limiting (~10 requests per second) but does not automatically retry HTTP 429 responses.

curl -X POST "https://api.example.com/api/v1/integrations/<ENTITY_ID>/execute" \
  -H "X-API-Key: <API_KEY>" \
  -H "X-Tenant-ID: <TENANT_ID>" \
  -H "Content-Type: application/json" \
  -d '{
    "operation": "test"
  }'
{
  "success": true,
  "data": {
    "message": "ActiveCampaign connection test successful",
    "details": {
      "api_base_url": "https://<ACCOUNT>.api-us1.com/api/3"
    }
  }
}

Sync and batch operations

Use sync to run an optional outbound send followed by an optional inbound receive in one call. Empty outbound/inbound objects are skipped (legacy empty() semantics).

Use batch to run multiple send/receive sub-operations sequentially. Each item uses operation (or type) and data (or sibling fields as callData). Failed items are recorded per index; the batch succeeds when at least one sub-operation succeeds.

Additional references

For endpoint-specific payload details, review the ActiveCampaign API overview and ActiveCampaign API reference. Keeping field mappings aligned with current API schema helps prevent unexpected sync failures.