Campaigns
Send one message to a contact group, several groups, or your whole contact book — created as a draft, dispatched when you say so, with live progress counters you can poll.
Campaigns live under /api/v1/ and authenticate with a scoped mbs_ token or JWT. A campaign targets contact groups (or an explicit phone list) and supports {{name}}-style personalization from your stored contact fields.
Create a campaign
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Internal label for the campaign — shows in lists and reports, never sent to recipients. |
| message | string | Yes | The message body. May contain personalization fields like {{name}} filled from each contact. |
| source_type | string | Yes | groups (send to the groups in target_group_uuids), all (every contact in your team), or manual (the phones in target_phones). |
| target_group_uuids | string[] | No | Group UUIDs to target — required when source_type is groups. |
| target_phones | string[] | No | Explicit recipient list — required when source_type is manual. Any accepted phone format. |
| sender_id | uuid | No | UUID of an approved sender ID. Omit to use your team's default sender. |
| skip_blacklisted | boolean | No | Skip recipients who opted out via the blacklist. Strongly recommended for promotional sends. |
| send_type | string | No | immediate (default) or scheduled with a scheduled_at ISO-8601 timestamp. |
| scheduled_at | RFC 3339 timestamp | No | When to dispatch a scheduled campaign, e.g. 2026-07-15T09:00:00+03:00. |
| name_field | string | No | Which contact field fills {{name}}: first_name (default) or full name. |
curl -X POST https://api.mobilesasa.com/api/v1/campaigns \
-H "Authorization: Bearer $MOBILESASA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "July offer — Nairobi customers",
"message": "Hi {{name}}, enjoy 20% off all orders this weekend. Dial *384# to redeem.",
"source_type": "groups",
"target_group_uuids": [
"7d1a44f0-…"
],
"sender_id": "9b2f6c1e-…",
"skip_blacklisted": true
}'{
"success": true,
"data": {
"uuid": "c4e8a90d-…",
"name": "July offer — Nairobi customers",
"status": "draft",
"source_type": "groups",
"message_parts": 1,
"total_recipients": 0,
"created_at": "2026-07-11T10:02:11Z"
}
}Draft first, send second
draft until you call the send endpoint — giving you a chance to review the rendered message and recipient count.Send it
Sending resolves the audience, computes total message parts, and reserves the SMS units from your balance up front— if the balance can't cover the whole campaign the call fails with an insufficient-balance error and nothing is sent. A scheduled campaign is queued for its scheduled_at time instead of dispatching immediately.
curl -X POST https://api.mobilesasa.com/api/v1/campaigns/c4e8a90d-…/send \
-H "Authorization: Bearer $MOBILESASA_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'Track progress
Poll the campaign for live counters; the recipients endpoint pages through per-recipient delivery state.
curl "https://api.mobilesasa.com/api/v1/campaigns/c4e8a90d-…" \
-H "Authorization: Bearer $MOBILESASA_TOKEN"{
"success": true,
"data": {
"uuid": "c4e8a90d-…",
"status": "sending",
"total_recipients": 4210,
"total_sent": 3900,
"total_delivered": 3711,
"total_failed": 12,
"total_blacklisted_skipped": 38,
"total_parts_sent": 3900,
"started_at": "2026-07-11T10:05:00Z"
}
}Campaign statuses
| Field | Type | Required | Description |
|---|---|---|---|
| draft | initial | No | Created but not sent. Editable (PUT) and deletable. |
| queued | in flight | No | Accepted for dispatch (or waiting for its scheduled time). |
| sending | in flight | No | Workers are fanning messages out; counters update live. |
| completed | final | No | All recipients processed. total_failed tells you how many didn't go out. |
| failed | final | No | The campaign as a whole failed — failure_reason says why (e.g. insufficient balance, no sender configured). |
| cancelled | final | No | Stopped via the cancel endpoint before finishing. |
Cancel
Cancels a draft or queued campaign — handy for calling off a scheduled send. Cancelling a queued campaign releases its reserved units back to your balance. Once a campaign is sending it can no longer be cancelled.
Resend
Resending a completed, failed or cancelled campaign clones it into a new campaign (new UUID) and dispatches the clone immediately — the original and its stats stay untouched. The response is the new campaign; store its UUID for tracking.
curl -X POST https://api.mobilesasa.com/api/v1/campaigns/c4e8a90d-…/resend \
-H "Authorization: Bearer $MOBILESASA_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'Resend re-bills
List campaigns
curl "https://api.mobilesasa.com/api/v1/campaigns?page=1&page_size=20" \
-H "Authorization: Bearer $MOBILESASA_TOKEN"