Skip to Content
API ReferenceCampaigns

Campaigns

Base path: /campaigns

Campaigns send a templated message to every active contact in a group, asynchronously. Unlike /sms/send, a campaign is queued and processed by a background worker rather than sent inline — expect total_delivered / total_failed to fill in over the following seconds to minutes, not instantly.

Create a campaign

POST /campaigns

{ "name": "July Promo", "message": "Hi {first_name}, enjoy 20% off this week only!", "group_id": "3fa85f64-...", "sender_id": null, "scheduled_at": null }
  • message supports merge tags {first_name} and {last_name}, resolved per-recipient by the worker from your Contacts data.
  • group_id — required; the campaign targets every non-opted-out contact in this group.
  • scheduled_at — omit to send immediately (status: "queued"), or pass a future datetime to schedule it (status: "scheduled") — picked up automatically once due.

Cost is calculated and debited from your wallet upfront, based on your current pricing tier. 400 if the group has no active contacts; 402 if your balance can’t cover the cost.

List campaigns

GET /campaigns — all your campaigns, newest first.

Get a campaign

GET /campaigns/{campaign_id}

Campaign report

GET /campaigns/{campaign_id}/report

{ "campaign": { "id": "...", "name": "July Promo", "status": "completed", "...": "..." }, "stats": { "total_recipients": 500, "delivered": 480, "failed": 12, "pending": 8, "delivery_rate": 96.0 }, "cost_kes": 240.0, "started_at": "2026-07-01T09:00:03Z", "completed_at": "2026-07-01T09:04:11Z" }

Campaign statuses

draftqueued / scheduledsendingcompleted | failed

Last updated on