Campaigns
Broadcast targeted WhatsApp template messages to thousands of contacts — immediately or on a schedule, with real-time delivery tracking.
What is a Campaign?
A Campaign sends an approved Meta template message to a list of contacts in a single action. Every recipient gets an individual WhatsApp conversation — not a group message.- Only Meta-approved templates can be used (required for business-initiated conversations).
- Can be launched immediately or scheduled for any future date and time.
- Scheduled campaigns launch automatically — no manual action needed when the time arrives.
- Built-in real-time delivery tracking: sent, delivered, read, failed, and queued counts update live.
- Contacts who have opted out are automatically excluded.
Creating a Campaign
1
Open Campaigns → New Campaign
Click New Campaign. Give it a descriptive internal name (visible only to your team, not recipients).
2
Select a WhatsApp account and template
Pick the connected WhatsApp number and an approved template from the dropdowns. A live template preview appears on the right side of the form, showing the header, body, footer, and buttons exactly as recipients will see them.
3
Map template variables
If your template contains placeholders like
{{1}}, {{2}}, map each one to either:- Static Text — the same value for every recipient (e.g. a discount code, event name).
- From Contact — a contact field: Name, Phone, Email, or any of your custom fields (cf1–cf10).
4
Add header media (if required)
If your template has an IMAGE, VIDEO, or DOCUMENT header, a media section appears. Choose Upload (drag a file — it uploads to secure cloud storage and inserts the URL automatically) or URL (paste a direct public link). A thumbnail preview confirms the right file is selected.
5
Choose your audience
Select All Contacts (all opted-in contacts) or By Tags (only contacts with one of the specified tags). Opted-out and blocked contacts are always excluded regardless of audience selection.
6
Set schedule and rate limit
Choose Send Now or pick a future date and time for automatic launch. Adjust the rate limit (messages per second) — defaults to your org setting, max 80/sec per Meta limits.
7
Create and launch
Click Create Campaign. If scheduled, the campaign moves to Scheduled status and will launch automatically. If set to now, click Launch on the campaign card.
Warning
Meta limits business-initiated conversations per day based on your tier: Tier 1 = 1,000/day, Tier 2 = 10,000/day, Tier 3 = 100,000/day. Campaigns over your limit are queued and sent as capacity becomes available.
Real-Time Campaign Tracker
The campaign detail page auto-refreshes without any manual page reload:- Running campaigns refresh every 4 seconds.
- Scheduled campaigns refresh every 10 seconds (so you see the moment they launch).
- Paused campaigns refresh every 30 seconds.
- The Message Log tab shows per-contact status (Queued, Sent, Delivered, Read, Failed) and any error detail.
- Filter the log by status to quickly find failed messages.
Campaign Statuses
| Status | Meaning |
|---|---|
| Draft | Saved but not yet launched — no messages have been queued. |
| Scheduled | Will launch automatically at the specified date/time. No manual action needed. |
| Running | Messages are actively being sent through the queue. |
| Paused | Manually paused mid-send. Unsent messages remain queued and resume on un-pause. |
| Completed | All messages have been processed (sent or failed). |
| Failed | Campaign encountered a fatal error before sending. Check the error detail. |
Pausing and Resuming
You can pause a running campaign at any time — queued messages are held, in-flight messages finish. Click Resume to re-queue unsent messages and continue sending. The remaining contacts pick up where the campaign left off.Retrying Failed Messages
After a campaign completes, if some messages failed you'll see a Retry Queued button on the tracker page. Clicking it re-queues only the failed and stuck messages — already-sent messages are not re-sent. This is useful for transient errors (rate limits, network timeouts) without re-running the entire campaign.URL Button Variables
If your template has a URL button with a dynamic suffix (e.g.https://yoursite.com/{{1}}):- Map the variable to a contact field or static value just like body variables.
- If the resolved value is empty for a contact, the button component is omitted for that recipient rather than sending an invalid URL.
- Values are URL-encoded automatically — spaces and special characters are handled.
Tip
For per-recipient tracking links, use a custom field (e.g. cf2 = "Tracking Token") and map the button variable to that field.
Analytics
The campaign tracker shows live stats:- Total — audience size at the time the campaign was launched.
- Queued — messages waiting to be sent (decreases as campaign progresses).
- Sent — dispatched to WhatsApp's API successfully.
- Delivered — reached the recipient's device (double grey tick).
- Read — opened by the recipient (double blue tick).
- Failed — permanently failed after all retry attempts.
Sending via API
UsePOST /api/v1/campaigns/send to launch a broadcast campaign programmatically — from your backend, a webhook handler, or a cron job — without using the dashboard. Recipients are provided inline in the request body and do not need to be pre-registered as contacts.Tip
commonVariables saves you from repeating shared values (brand name, event date, promo code) on every recipient object. Only list per-recipient overrides in
recipients[].variables. The final value for each placeholder is { ...commonVariables, ...recipient.variables }.POST /api/v1/campaigns/send
Content-Type: application/json
Authorization: Bearer motherbot_xxx
{
"name": "Order Dispatch — June batch",
"templateName": "order_confirmation",
"languageCode": "en_US",
// These values apply to every recipient. No need to repeat them.
"commonVariables": {
"1": "MotherBot Store",
"3": "support@mystore.com"
},
"headerMediaUrl": "https://cdn.mystore.com/banner.jpg",
"rateLimitPerSecond": 10,
"recipients": [
// {{2}} (order ID) is different per recipient — only that key is provided
{ "to": "919876543210", "name": "John Smith", "variables": { "2": "ORDER-9912" } },
{ "to": "918765432109", "name": "Priya Sharma", "variables": { "2": "ORDER-9913" } },
// No variables at all — all three placeholders come from commonVariables
{ "to": "917654321098", "name": "Ravi Kumar" }
]
}
# Response 201
{
"success": true,
"data": {
"campaignId": "665d4c...",
"status": "running",
"total": 3,
"rateLimitPerSecond": 10,
"etaSeconds": 1,
"etaText": "~1 second"
}
}Once the campaign is running, poll its progress with GET /api/v1/campaigns/:campaignId/stats. The campaign also appears in the dashboard under Campaigns with a Source badge of API so you can distinguish API-launched campaigns from platform-launched ones.- Up to 100,000 recipients per request. Duplicate phone numbers are automatically deduplicated.
- templateId (MongoDB ID) or templateName + languageCode — both are accepted.
- Templates must be APPROVED. Pending or rejected templates return HTTP 400.
- rateLimitPerSecond defaults to 3 and is capped at 80 (Meta limit).
- Large lists are chunked and enqueued in the background — the API returns immediately with a campaignId.
Best Practices
- Always personalize with contact name or a custom field — campaigns with personalization see 30–40% higher read rates.
- Send during business hours in your audience's timezone.
- Keep your opt-out rate below 2% to protect your Meta quality rating.
- Test with a small tag group (10–20 contacts) before launching to your full list.
- Use custom fields (cf1–cf10) to store per-contact values like order IDs, invoice numbers, or plan names for truly personalized sends.