Bulk email campaigns
One email to a contact group or an explicit list of up to 10,000 addresses — drafted, sent asynchronously, with live progress counters.
Create a campaign
POST/api/v1/email/campaigns
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Internal label. |
| domain_uuid | uuid | Yes | The verified domain to send from. |
| subject | string | Yes | Subject line. |
| html / text | string | Yes | At least one body. |
| from | string | No | Local part or full address on the domain; omit for the domain default. |
| source_type | string | Yes | group — email every contact in a contact group that has an email address; manual — the explicit list in to. |
| group_uuid | uuid | No | Required for group campaigns. |
| to | string[] | No | Manual audience, up to 10,000 addresses. |
curl -X POST https://api.mobilesasa.com/api/v1/email/campaigns \
-H "Authorization: Bearer $MOBILESASA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "July newsletter",
"domain_uuid": "7c2e91d4-…",
"subject": "What's new at Yourbrand this July",
"html": "<h1>Hello!</h1><p>Here's what we shipped…</p>",
"source_type": "group",
"group_uuid": "9d0b33a1-…"
}'Send it
POST/api/v1/email/campaigns/{uuid}/send
Creating never sends. The send call queues the campaign for the fan-out worker (a second send call returns 409) — recipients are resolved, suppressed addresses skipped, and each remaining recipient is billed one unit as its email goes out at a provider-friendly pace.
curl -X POST https://api.mobilesasa.com/api/v1/email/campaigns/7f31ab02-…/send \
-H "Authorization: Bearer $MOBILESASA_TOKEN" \
-H "Content-Type: application/json" \
-d '{}'Track progress
GET/api/v1/email/campaigns/{uuid}
GET/api/v1/email/campaigns
curl "https://api.mobilesasa.com/api/v1/email/campaigns/7f31ab02-…" \
-H "Authorization: Bearer $MOBILESASA_TOKEN"Response — 200
{
"success": true,
"data": {
"uuid": "7f31ab02-…",
"name": "July newsletter",
"status": "completed",
"source_type": "group",
"total_recipients": 1874,
"total_sent": 1791,
"total_suppressed": 74,
"total_failed": 9,
"started_at": "2026-07-12T08:00:04Z",
"completed_at": "2026-07-12T08:02:41Z"
}
}Campaign statuses
| Field | Type | Required | Description |
|---|---|---|---|
| draft | initial | No | Created, not sent. |
| queued / sending | in flight | No | Waiting for or being processed by the fan-out worker; counters update live. |
| completed | final | No | Every recipient processed — see the sent/suppressed/failed split. |
| failed | final | No | The campaign stopped — failure_reason says why (most commonly insufficient email balance; recipients already sent stay sent and billed). |
Balance covers the whole audience
Recipients are billed in batches as the campaign runs. If your email balance runs out mid-campaign the campaign fails at that point with the partial counts recorded — top up and send a fresh campaign to the remainder. Pre-check: audience size × your email rate ≤ balance.