1. Campaign
Chronox AI API Referance
  • Get Started
    • Introduction
    • Authentication
    • Rate limiting
    • Errors
    • Pagination
    • Campaign
  • Account
    • Get User Details
      GET
    • Get Meta Integration
      GET
    • Get Integrated Channels
      GET
    • Get WABA Catalogs
      GET
  • WhatsApp Templates
    • Getting started
    • Templates
      • Create Whatsapp Template Guide
      • Get Whatsapp Templates
      • Get Whatsapp Template Details
      • Create Whatsapp Template
    • Lookups
      • Get Whatsapp Template Category
      • Get Whatsapp Languages
      • Get Whatsapp Template Type
      • Get Whatsapp Template Interactive Type
      • Get Whatsapp Template Header Type
      • Get Whatsapp Template Button Type
      • Get Whatsapp Template Dynamic Variable Type
  • Messaging
    • Getting started
    • Send Whatsapp Message
      POST
    • Send Whatsapp Template
      POST
    • Send Canned Response
      POST
  • Inbox
    • Get Inbox Data
      GET
    • Get Thread Details
      GET
    • Update Thread Archive
      PUT
    • Assign Thread Tags
      PUT
    • Assign Thread Status
      PUT
    • Update Thread Notes
      PUT
    • Get Canned Responses
      GET
    • Get Tags
      GET
    • Get Thread Status Types
      GET
  • Contact List
    • Getting started
    • Get Contact List
    • Create Contact List
    • Update Contact List
    • Update Contact List Status
    • Delete Contact List
  • Contacts
    • Getting started
    • Get Contacts
    • Create Contacts
    • Update Contact
    • Delete Contact
    • Delete Contact Copy
  • Tags and fields
    • Contact Tags
      • Get contact tags
      • Create contact tags
      • Update contact tag
      • Delete contact tag
    • Contact Fields
      • Get contact fields
      • Create contact fields
      • Update contact field
      • Delete contact field
  • Campaign
    • Getting Started
    • Campaign APIs
      • Create campaign
      • Get campaign
      • Update campaign
      • Delete campaign
      • Run campaign
      • Pause campaign
      • Resume campaign
      • Archive campaign
      • Get campaign Stats
    • Lookup
      • Get Statuses
      • Get campaign execution statuses
      • Get campaign contact filter types
      • Get campaign message types
      • Get contact field types
      • Get template variable types
      • Get country codes
  • Whatsapp Flow
    • Get Whatsapp flows
  • Tickets
    • Getting started
    • Get Tickets
    • Create Ticket
    • Update Ticket
    • Get Ticket Statuses
    • Get Agents
  • Organization Teams
    • Get Organization Teams
  • Template Library
    • Get Template Library
    • Get Template Drafts
  • CRM
    • Import leads (single or bulk)
    • List leads
    • Get lead detail
  • Schemas
    • Thread Execution Data
    • LeadImportField
    • LeadImportContact
    • Single lead
    • LeadImportBulkLead
    • Bulk (leads[])
    • LeadImportWarning
    • Single result
    • Bulk result
    • ApiError
    • ErrorEnvelope
    • Lead detail
    • Lead list row
    • Lead list
  1. Campaign

Getting Started

Getting Started with Campaigns#

A campaign sends one WhatsApp message (a template) to the contacts of one contact list. This page explains, step by step, how to create a campaign, change it, run it, follow its progress, and pause, resume, archive or delete it. You don't need to be a developer. If you can fill in a form, you can write the request.

1. The big picture#

Create  →  (Update)  →  Run  →  Follow progress  →  Completed  →  Archive / Delete
                          │
                          └→  Pause  →  Resume
1.
Create a campaign. It starts as Draft, or as Scheduled if you give it a date and time.
2.
Update it if you want to change anything. Only Draft and Scheduled campaigns can be changed.
3.
Run it. The messages go out in the background.
4.
Follow progress with Get campaign. When every message has been handled, the campaign becomes Completed by itself.
5.
Pause a running campaign if you need to stop. Resume it later and it carries on with the contacts that haven't been sent yet.
6.
Archive a campaign you no longer need to see, or Delete one you never ran.

2. Before you create a campaign: what you need#

A campaign body is mostly numbers called IDs. An ID is just the number the system gave to something (a contact list, a template, and so on). Collect these first. Each row tells you where to find the number.
What you needWhat it looks likeWhere to find it
Your API keyext-...Sent in the header Authorization: Bearer ext-<your-api-key> on every request.
A contact list with contacts in itcontact_list_id, for example 12GET /contact/list. The list must not be archived.
The WhatsApp phone number that will send the messagemeta_integration_whatsapp_phone_number_id, for example 5GET /meta-integration
The message templatewhatsapp_template_id, for example 40GET /meta-integration/{meta_integration_whatsapp_id}/whatsapp-template
The template's variableswhatsapp_template_dynamic_variable_id, for example 210In the same template response. A variable is a gap in the message, like {{1}} in "Hi {{1}}, your order is ready".
The kind of messagecampaign_message_type_id, for example 1GET /global/campaign-message-type (no key needed).
The contact fields that fill the template gapscontact_field_id, for example 2 for First NameGET /contact/field?contact_list_id=12
(Optional) tags, to send to only some contactscontact_tag_id, for example 9GET /contact/tag?contact_list_id=12
Two rules about the template:
It must be approved by WhatsApp.
Authentication templates (the ones that send login codes) can't be used in campaigns.

3. Create a campaign#

POST /campaign

3.1 The simplest request#

This sends one approved template to every contact of a list. Replace each number with your own IDs. Everything in quotes that isn't a number is text you can change.
{
    "campaign_title": "October Offer",
    "contact_list_id": 12,
    "campaign_message_type_id": 1,
    "flag_template": true,
    "whatsapp_template_id": 40,
    "meta_integration_whatsapp_phone_number_id": 5,
    "campaign_message_content": "",
    "campaign_message_sending_date": null,
    "campaign_message_sending_time": null,
    "contact_tag_id": [],
    "campaign_variable": [
        {
            "contact_field_id": 2,
            "whatsapp_template_dynamic_variable_id": 210,
            "campaign_variable_name": "First Name",
            "campaign_variable_fallback_value": "Customer"
        }
    ],
    "campaign_carousel_card": []
}

3.2 What each line means#

LineIn plain wordsRequired?
campaign_titleThe name of the campaign. It must be different from every other campaign you have.Yes
contact_list_idThe list of people who will get the message.Yes
campaign_message_type_idThe kind of message. Use an ID from the message types lookup. You can leave it out for a follow-up campaign (section 5).Yes
flag_templateAlways true when you send a template.Yes
whatsapp_template_idThe template you want to send.Yes
meta_integration_whatsapp_phone_number_idThe WhatsApp number the message is sent from.Yes
campaign_message_contentLeave it as "" (empty) when you send a template.Yes, keep ""
campaign_message_sending_dateThe day to send, as YYYY-MM-DD, for example "2030-12-31". Leave it null to send when you press run.No
campaign_message_sending_timeThe time to send, as HH:MM in 24-hour time, for example "09:30". Leave it null to send when you press run.No
contact_tag_idSend only to contacts with these tags. [] means everyone in the list.No
campaign_variableFills the gaps in the template. See 3.3.Yes, if the template has gaps
campaign_carousel_cardOnly for carousel templates. See section 6. Otherwise leave [].No
You don't need to send waba_id. It isn't used.

3.3 Filling the gaps in the template (variables)#

Many templates have gaps. For example:
Hi {{1}}, your order {{2}} is ready.
The body needs one block for each gap. A block tells the system where to get the text for that gap:
{
    "contact_field_id": 2,
    "whatsapp_template_dynamic_variable_id": 210,
    "campaign_variable_name": "First Name",
    "campaign_variable_fallback_value": "Customer"
}
whatsapp_template_dynamic_variable_id: which gap this block fills. Take it from the template details.
contact_field_id: the contact field to read the text from. Each person's own value is used, so John gets "Hi John" and Asha gets "Hi Asha".
campaign_variable_fallback_value: the text to use when a contact has nothing in that field, so nobody gets an empty gap.
campaign_variable_name: a label for you. It doesn't change the message.
Rules:
Every gap needs a block. A block needs a contact_field_id, a fallback value, or both.
If you want the same text for everyone, leave out contact_field_id and write only the fallback value.
Don't use the same gap in two blocks.
Example for two gaps:
"campaign_variable": [
    {
        "contact_field_id": 2,
        "whatsapp_template_dynamic_variable_id": 210,
        "campaign_variable_name": "First Name",
        "campaign_variable_fallback_value": "Customer"
    },
    {
        "whatsapp_template_dynamic_variable_id": 211,
        "campaign_variable_name": "Order Number",
        "campaign_variable_fallback_value": "your order"
    }
]

3.4 Send later (schedule it)#

Fill both the date and the time:
"campaign_message_sending_date": "2030-12-31",
"campaign_message_sending_time": "09:30"
The campaign gets the status Scheduled and is started automatically at that time. You don't need to press run.
The date and time must be in the future.
Use exactly this format: YYYY-MM-DD and HH:MM. Fill both or neither.
To cancel the schedule, update the campaign and set both back to null. It becomes a Draft again.

3.5 Send to only some contacts (tags)#

Tags are labels you put on contacts, like "VIP". To send only to tagged contacts, list the tag IDs:
"contact_tag_id": [9, 14]
Contacts that have at least one of those tags are included. Every tag must be a tag of the contact list you chose (or a general tag that every list can use).

3.6 What you get back#

A successful call returns the new campaign. The important parts:
campaign_id: write this number down. You need it to update, run, pause and archive the campaign.
campaign_execution_status_name: Draft or Scheduled.
total_campaign_contact: how many contacts will get the message.
campaign_contact_assignment_data: the list of contacts in the campaign, each with the message prepared for them, so you can check who will get it before you run.

4. Update a campaign#

PUT /campaign
Works only while the status is Draft or Scheduled.
Send the whole body again, like in Create, and add the campaign's number: "campaign_id": 123. Whatever you send replaces what was saved.
Variables: put each existing block's campaign_variable_id (you can see it in Get campaign). Use 0 for a new block. A block you leave out is removed.
Carousel cards: the same idea with campaign_carousel_card_id. A card you leave out is removed.
Follow-up filters: if you leave out campaign_contact_filter, or send [], the filters are removed.
Changing the name to one that another campaign already uses is not allowed.
Tip: the easiest way is to call Get campaign, copy what you want to keep into your update body, and change only the parts you need.

5. A follow-up campaign (send to the people who reacted a certain way)#

A follow-up campaign is a new campaign for people from an earlier campaign, chosen by what happened to their message. For example: "everyone who got the message but didn't read it", or "everyone whose message failed".
Add these lines to the create body:
"retargeted_from_campaign_id": 123,
"campaign_contact_filter_logic_operator": "OR",
"campaign_contact_filter": [
    {
        "campaign_contact_filter_type_id": 1,
        "campaign_contact_filter_type_name": "Campaign Execution Status",
        "campaign_contact_filter_type_data": [
            { "campaign_contact_filter_unique_id": 4, "campaign_contact_filter_unique_value": [] },
            { "campaign_contact_filter_unique_id": 8, "campaign_contact_filter_unique_value": [] }
        ]
    }
]
What each line means:
LineIn plain words
retargeted_from_campaign_idThe earlier campaign whose contacts you want to pick from.
campaign_contact_filter_type_idThe kind of filter. Take it from GET /global/campaign-contact-filter-type. "Campaign Execution Status" filters by what happened to the message. "Contact Field" filters by a value in a contact's details.
campaign_contact_filter_unique_idFor "Campaign Execution Status": the ID of the status, such as Read or Failed, from GET /global/campaign-execution-status. For "Contact Field": the contact_field_id.
campaign_contact_filter_unique_valueFor "Campaign Execution Status": always []. For "Contact Field": the values to match, for example ["Mumbai", "Pune"].
campaign_contact_filter_logic_operatorPut it once, at the top of the body, next to campaign_title. Use "OR" or "AND", as explained below.
OR or AND?
"OR": a contact is picked if it matches any of your statuses. Example: Delivered or Failed.
"AND" (the default): a contact must match all of your statuses at once. Example: Delivered and Read.
If you're not sure, use "OR".
Good to know:
Pick the same contact list the earlier campaign used, so the contacts match.
In a follow-up you can leave out campaign_message_type_id.
If nobody matches your filter, the request fails. Pick other statuses or check the earlier campaign's results.

6. Carousel templates#

A carousel template shows several cards. You send one card block for each carousel variation of the template. You can see the variation numbers in the template details.
"campaign_carousel_card": [
    {
        "whatsapp_template_carousel_variation_id": 501,
        "campaign_carousel_card_index": 0,
        "campaign_variable": [
            {
                "contact_field_id": 2,
                "whatsapp_template_dynamic_variable_id": 330,
                "campaign_variable_name": "First Name",
                "campaign_variable_fallback_value": "Customer"
            }
        ]
    },
    {
        "whatsapp_template_carousel_variation_id": 502,
        "campaign_carousel_card_index": 1,
        "campaign_variable": []
    }
]
campaign_carousel_card_index is the position of the card: 0 for the first, 1 for the second, and so on.
A card's campaign_variable works exactly like section 3.3, but only for that card's gaps. Check the template details to see which gaps belong to which card.
Sending a missing, extra or repeated variation fails the request.

7. Run a campaign#

POST /campaign/run-campaign
{
    "campaign_id": 123
}
Works for a Draft or Scheduled campaign (starts it) and for a Paused campaign (continues it).
It answers quickly with { "status": true }. The messages are sent in the background, so the campaign takes a while to finish. Follow the progress with Get campaign (section 8).
A scheduled campaign starts by itself at its time. You only press run if you want to send it earlier.
Checks made before sending. If one fails, nothing is sent:
The campaign has contacts. If contacts were deleted from the list after you created the campaign, the run is refused. Create a new campaign.
Your organization isn't paused by an admin.
Your WhatsApp account is in good standing and you haven't used up your message limit.
What the system does on its own while sending:
A contact who has opted out of marketing messages is skipped and gets the status Opted Out.
A contact who is known to be undeliverable is skipped and gets the status Message Undelivered.
If a serious problem happens (for example your WhatsApp account has an issue), the campaign pauses itself. Fix the problem, then resume.
When every contact has been handled, the campaign becomes Completed.

8. Follow the progress#

GET /campaign?campaign_id=123
Look at these:
FieldWhat it tells you
campaign_execution_status_nameWhere the campaign is: Draft, Scheduled, In Progress, Paused, Completed or Archived.
total_campaign_contactHow many contacts the campaign has.
total_sent_campaign_contactMessages sent.
total_delivered_campaign_contactMessages that reached the phone.
total_read_campaign_contactMessages that were read.
total_pending_campaign_contactContacts still waiting.
total_failed_campaign_contactMessages that failed.
total_message_undelivered_campaign_contactContacts skipped because they can't receive messages.
total_opted_out_campaign_contactContacts skipped because they opted out.
total_contacts_who_clickedPeople who clicked a button or link.
total_contacts_who_repliedPeople who replied.
campaign_contact_assignment_dataOne entry per contact, with that contact's own status and the reason if it failed (failure_reason).
Without campaign_id, GET /campaign gives a short summary of all your campaigns. GET /campaign/multiple-campaign gives combined numbers for your Completed campaigns. You can add campaign_ids=1,2 and start_date / end_date (for example 2026-01-01) to narrow it down.

9. Pause, resume, archive and delete#

ActionRequestBodyWhen you can do it
PausePOST /campaign/pause-campaign{ "campaign_id": 123, "pause_reason": "Fixing the message" }Only while the campaign is In Progress. pause_reason is optional.
ResumePOST /campaign/resume-campaign{ "campaign_id": 123 }Only while it is Paused. It carries on with the contacts not yet sent.
ArchivePOST /campaign/archive-campaign{ "campaign_id": 123 }Any campaign except one that is In Progress or already Archived.
DeleteDELETE /campaign?campaign_id=123none: the number goes in the web addressOnly Draft or Scheduled campaigns.
Pausing stops the sending as soon as the current message is done. Messages that were already sent are not recalled.

10. What each status means#

Campaign statuses
StatusMeaningWhat you can do
DraftCreated, not sent, no schedule.Update, run, delete, archive
ScheduledCreated with a date and time. It starts by itself.Update, run now, delete, archive
In ProgressMessages are being sent.Pause
PausedStopped, by you or by the system.Resume, archive
CompletedEvery contact has been handled.Archive
ArchivedHidden away.Nothing
Contact statuses (one per contact, inside campaign_contact_assignment_data)
StatusMeaning
PendingWaiting to be sent.
SentSent from your WhatsApp number.
DeliveredReached the person's phone.
ReadThe person opened it.
FailedWhatsApp could not send it. The reason is in failure_reason.
Message UndeliveredSkipped, because this number can't receive messages.
Opted OutSkipped, because the person chose to stop receiving marketing messages.
Clicked / RepliedThe person clicked a button or link, or replied.

11. Common errors and what to do#

Every error looks like this: { "status": false, "error": { "code": 9001, "message": "..." } }.
CodeWhat happenedWhat to do
9001 Invalid bodySomething in your request is missing or wrong.Check the required lines in section 3.2. Check the date and time format. Check that the list, template and phone number IDs exist, that every gap has a variable block, and that the campaign is in the right status for what you're doing.
9436 Campaign name already existsAnother campaign has this title.Use a different campaign_title.
9303 Authentication templates can't be usedYou picked a login-code template.Pick a marketing or utility template.
9330 Contact list is archivedThe list is archived.Use another list, or make the list Active again.
9032 Data not foundThe campaign has no contacts.Add contacts to the list and create the campaign again.
9244 The contact list has been updatedContacts were deleted after the campaign was created.Delete the campaign and create a new one.
9245 Cannot resumeSame reason, while resuming.Create a new campaign.
9246 Organization is pausedAn admin paused your organization.Contact your admin.
9002 Invalid query parameterThe number in the web address is missing or wrong, or the campaign can't be deleted in its current status.Check campaign_id, and that the campaign is Draft or Scheduled.
401 Invalid or expired API keyThe key is wrong or has expired.Create a new key.
403 Access not grantedYour key isn't allowed to use this API.Ask your admin.

12. Quick checklist before you press run#

The contact list is active and has the right contacts.
You picked an approved template that isn't an authentication template.
Every gap in the message has a variable block.
You looked at campaign_contact_assignment_data and the contacts in it are the ones you want.
The number of contacts in total_campaign_contact is what you expect.
If you scheduled it, the date and time are right and in the future.
You wrote down the campaign_id.
Modified at 2026-10-21 04:46:21
Previous
Delete contact field
Next
Create campaign
Built with