Platform
Chatbot Builder Bulk Messaging Team Inbox Mini CRM API & Webhooks AI Integration WhatsApp Flows
Industries
E-commerce & D2C Real Estate Education Healthcare Finance & BFSI Logistics Hospitality Retail
Integrations
Learn
Learning Hub Help & Docs Connect Guides Automation Codex Blog Message Templates
Pricing Start Free Trial →
HomeConnect › Connect ActiveCampaign to WhatsApp
ActiveCampaign Integration Guide · Marketing / Email

Connect ActiveCampaign to WhatsApp

Add every WhatsApp opt-in to your ActiveCampaign contact list, search existing contacts before personalising a message, and trigger automations from WhatsApp, all without manually importing a CSV.

Published 23 June 2026  ·  6 min read  ·  Marketing / Email

Before following this guide, read the External API Request step foundation guide. It covers every field in the step interface so this guide can focus on ActiveCampaign-specific values.

Auth header is Api-Token and the base URL is account-specific

ActiveCampaign uses Api-Token: YOUR_TOKEN as the header name, not Authorization. The base URL is also unique to your account: https://YOURACCOUNTNAME.api-us1.com/api/3/. Both are found in Settings → Developer. Wrong subdomain means no connection.

Step 1: Get your API URL and token

1
In ActiveCampaign, click Settings (bottom left cog) → Developer.
2
Copy your API URL, for example: https://youraccountname.api-us1.com. This is your base URL for all calls.
3
Copy your API Token. Use it as the value of the Api-Token header on every request.
Official docs

ActiveCampaign API v3: developers.activecampaign.com

Step 2: Get your List ID

List IDs in ActiveCampaign are integers. You can also find them in the URL when you view a list in the UI. The API confirms them reliably.

External API Request Step · WA.Expert
Select Method
GET
Request URL
https://YOURACCOUNTNAME.api-us1.com/api/3/lists
Select Auth Type
No Auth (Api-Token in header below)
Header Parameters
Api-TokenYOUR_ACTIVECAMPAIGN_API_TOKEN
Acceptapplication/json
Select Body Type
None (GET, no body)
Choose Response Type
JSON
GET /api/3/lists response
{{
  "lists": [
    {{
      "id": "2",
      "name": "WhatsApp Opt-Ins",
      "subscriber_count": "1843"
    }}
  ],
  "meta": {{"total": "1"}}
}}

Copy: lists[0].id = "2"  (use as integer when subscribing)

Step 3: Search for a contact by email

Before adding a contact, check whether they already exist. Pass the email as a query parameter.

External API Request Step · WA.Expert
Select Method
GET
Request URL
https://YOURACCOUNTNAME.api-us1.com/api/3/contacts?email={{{{customer_email}}}}
Select Auth Type
No Auth (Api-Token in header below)
Header Parameters
Api-TokenYOUR_ACTIVECAMPAIGN_API_TOKEN
Acceptapplication/json
Select Body Type
None (GET, no body)
Choose Response Type
JSON
GET /api/3/contacts?email= response
{{
  "contacts": [
    {{
      "id": "21",
      "email": "priya@example.com",
      "firstName": "Priya",
      "lastName":  "Sharma",
      "phone":     "+919820000001"
    }}
  ],
  "meta": {{"total": "1"}}
}}

Map: contacts[0].id -> contact_id
     contacts[0].firstName -> contact_name
If contacts array is empty, the contact does not exist -> run Step 4.

Step 4: Create a contact (if new)

External API Request Step · WA.Expert
Select Method
POST
Request URL
https://YOURACCOUNTNAME.api-us1.com/api/3/contacts
Select Auth Type
No Auth (Api-Token in header below)
Header Parameters
Api-TokenYOUR_ACTIVECAMPAIGN_API_TOKEN
Content-Typeapplication/json
Acceptapplication/json
Select Body Type
JSON
Body
{{"contact":{{"email":"{{{{customer_email}}}}","firstName":"{{{{customer_name}}}}","phone":"{{{{customer_phone}}}}"}}}}
Choose Response Type
JSON
POST /api/3/contacts body and response
Body:
{{
  "contact": {{
    "email":     "{{customer_email}}",
    "firstName": "{{customer_name}}",
    "phone":     "{{customer_phone}}"
  }}
}}

Response (HTTP 201):
{{
  "contact": {{
    "id":        "21",
    "email":     "priya@example.com",
    "firstName": "Priya"
  }}
}}

Map: contact.id -> contact_id
Note: response wraps contact in a 'contact' key (singular),
not 'contacts' (plural) like the search endpoint.
contact vs contacts in responses

The search endpoint returns a contacts array: contacts[0].id. The create endpoint returns a single contact object: contact.id. These are different keys. Use the right path for each step.

Step 5: Subscribe the contact to a list

With {{contact_id}} from Step 3 or 4, and your list ID, subscribe them:

External API Request Step · WA.Expert
Select Method
POST
Request URL
https://YOURACCOUNTNAME.api-us1.com/api/3/contactLists
Select Auth Type
No Auth (Api-Token in header below)
Header Parameters
Api-TokenYOUR_ACTIVECAMPAIGN_API_TOKEN
Content-Typeapplication/json
Acceptapplication/json
Select Body Type
JSON
Body
{{"contactList":{{"list":2,"contact":"{{{{contact_id}}}}","status":1}}}}
Choose Response Type
JSON
POST /api/3/contactLists body and response
Body:
{{
  "contactList": {{
    "list":    2,
    "contact": "{{contact_id}}",
    "status":  1
  }}
}}

Response (HTTP 200):
{{
  "contactList": {{
    "contact": "21",
    "list":    "2",
    "status":  "1"
  }}
}}

status: 1 = subscribed
status: 2 = unsubscribed
status: 0 = unknown

Idempotent: re-subscribing an already-subscribed contact returns 200 again.

Response field mapping:

VariableSourceExample value
contact_idStep 3: contacts[0].id or Step 4: contact.id21
contact_nameStep 3: contacts[0].firstNamePriya
list_idStep 2: lists[0].id (use as integer)2

Store contact_id and list_id as flow variables to avoid re-fetching on every run.

Worked example: WhatsApp opt-in to ActiveCampaign

Automation flow — sync WhatsApp opt-in to ActiveCampaign
Trigger: Customer messages 'SUBSCRIBE' on WhatsApp.

Captured: {{customer_email}} = priya@example.com
          {{customer_name}}  = Priya Sharma
          {{customer_phone}} = +919820000001

Step 1 — Search contact:
GET https://youraccountname.api-us1.com/api/3/contacts
  ?email=priya@example.com
Api-Token: YOUR_TOKEN

Response: meta.total = 0 (not found)

Conditions: if total > 0 -> use contacts[0].id as contact_id, skip to Step 3
            if total = 0 -> run Step 2

Step 2 — Create contact:
POST https://youraccountname.api-us1.com/api/3/contacts
Body: {{"contact":{{"email":"priya@example.com","firstName":"Priya",
        "phone":"+919820000001"}}}}

Response: contact.id = '21'
Stored as {{contact_id}}.

Step 3 — Subscribe to list:
POST https://youraccountname.api-us1.com/api/3/contactLists
Body: {{"contactList":{{"list":2,"contact":"{{contact_id}}","status":1}}}}

Response: HTTP 200, contactList.status = '1'

Bot replies:
'You are now subscribed, Priya! You will receive our updates
at priya@example.com.'

Troubleshooting

SymptomLikely causeFix
401 UnauthorizedWrong header nameUse Api-Token as the header name, not Authorization. Confirm the token value from Settings → Developer.
Connection refused or timeoutWrong account URLYour base URL is account-specific. Copy it from Settings → Developer exactly. A wrong subdomain (e.g. .api-us2.com vs .api-us1.com) returns a connection error.
contacts array emptyContact not in ActiveCampaignThe email does not exist. Proceed to Step 4 to create the contact.
contact vs contacts confusionDifferent response shapesGET /contacts returns contacts[] array. POST /contacts returns contact singular object. Use contacts[0].id for search results and contact.id for create response.
422 on contactListsContact ID or list ID is wrong typeThe contact field accepts a string or integer. The list field must be an integer (2, not '2'). Confirm both IDs are valid.
429 Too Many RequestsRate limit exceededCheck the Retry-After header and wait before retrying. For a WhatsApp bot doing single lookups, this limit is very generous.

Common questions

What header does ActiveCampaign use for auth?
+
Api-Token: YOUR_API_TOKEN. Not Authorization. Found in Settings → Developer alongside your account URL.
Where do I find my API URL and token?
+
Settings → Developer. Copy both the API URL (your account subdomain) and the API Token.
How do I subscribe a contact to a list?
+
POST /api/3/contactLists with contactList.list (integer), contactList.contact (contact ID), contactList.status = 1.
Can I search by email?
+
Yes. GET /api/3/contacts?email=EMAIL. Returns contacts array. Empty array = not found. contacts[0].id is the contact ID.
What does status 1 mean in contactLists?
+
1 = subscribed, 2 = unsubscribed, 0 = unknown. Always pass 1 for opt-ins.
Does this incur extra WA.Expert charges?
+
One automation action per External API Request call. Included on the Complete plan. Starter: from Rs. 49 per 1,000 actions.
Is this the same as ActiveCampaign's own WhatsApp Messaging feature?
+
No — ActiveCampaign now offers native WhatsApp Messaging (via its Hilos acquisition) with a shared multi-agent inbox and its own flow builder, available on all plans. That's the right choice if you want your team chatting with contacts directly inside ActiveCampaign. This guide covers something different: syncing WhatsApp opt-ins and contact lookups into ActiveCampaign via API for a WA.Expert chatbot, which can run independently of or alongside ActiveCampaign's native messaging.

Connect ActiveCampaign to WhatsApp today

3-day free trial, no credit card. If you get stuck, we answer live on WhatsApp.

Start Free Trial → Book a Demo
1