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 *657# 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"