Send template messages
One call sends an approved template to one recipient or a list, with the same values for everyone or a set per person.
Parameters
| Field | Type | Required | Description |
|---|---|---|---|
| account_uuid | uuid | Yes | Which number to send from (your own or the Mobile Sasa number). The Account ID under WhatsApp, My numbers in the portal, or uuid from GET /api/v1/whatsapp/accounts. |
| template_uuid | uuid | Yes | An APPROVED template on that account. The Template ID on its card under WhatsApp, Templates, or uuid from the account's template list. |
| recipients | string[] | No | Phone numbers of opted-in recipients (Kenyan formats accepted, E.164 for everyone else). Use with params for the same values to all. |
| params | string[] | No | Values for the template's {{1}}, {{2}}… blanks, in order, applied to every number in recipients. For a passcode template this is the code. |
| personalized | object[] | No | Instead of recipients: [{ "to": "0712…", "params": ["Jane", "KES 1,200"] }, …], one set of values per person. Both forms may be combined in one call. |
| media_id | string | No | Meta media ID for templates with an image, video or document header. Upload with POST /api/v1/whatsapp/accounts/{uuid}/media (multipart file). |
# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"
curl -X POST https://api.mobilesasa.com/api/v1/whatsapp/send \
-H "Authorization: Bearer $MOBILESASA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account_uuid": "ACCOUNT_UUID",
"template_uuid": "TEMPLATE_UUID",
"personalized": [
{
"to": "0712345678",
"params": [
"Jane",
"February",
"KES 128,400"
]
},
{
"to": "0733000002",
"params": [
"Otieno",
"February",
"KES 4,050"
]
}
]
}'{
"success": true,
"data": {
"accepted": 2,
"rejected": 0,
"cost": 5.00,
"rate": 2.50
}
}accepted messages are queued and billed at rate each; rejected counts numbers that could not be parsed, listed in invalid. Duplicated numbers in one call are sent once.
Quote before you send
Same body as send. Nothing is sent or charged; you get the rate, the number of recipients after de-duplication, the total and your wallet balance.
# Paste your token once (it starts with mbs_):
export MOBILESASA_TOKEN="mbs_your_token_here"
curl -X POST https://api.mobilesasa.com/api/v1/whatsapp/quote \
-H "Authorization: Bearer $MOBILESASA_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"account_uuid": "ACCOUNT_UUID",
"template_uuid": "TEMPLATE_UUID",
"recipients": [
"0712345678",
"0733000002"
]
}'{
"success": true,
"data": { "rate": 2.50, "recipients": 2, "total": 5.00, "balance": 56048.50, "mode": "managed" }
}What a message costs
- Managed numbers (the Mobile Sasa number, or one we set up for you): the template category's rate per message.
- Your own Meta app: the flat platform fee per message. Meta bills the conversation to your Meta account separately.
The wallet is charged when the message is accepted. If Meta refuses it (not a WhatsApp number, policy block, template paused) the message is marked failed and the charge is refunded to your wallet automatically; refunded_at on the message says when.
Only the blanks are yours
Requirements and failure modes
- The template must be
APPROVED; pending, rejected or paused templates fail the whole call with a validation error. - Insufficient wallet balance fails the call before anything sends, with the amount needed in the error.
- Recipients must have opted in to WhatsApp messages from you. Meta scores every number on blocks and reports; a poor rating limits how many new people you can message per day.
- Marketing templates can only reach a person who has not received marketing from your number in the last day or so; Meta drops the extra ones (status
failed, refunded).
Track outcomes in message history; statuses move through queued → sent → delivered → read, with failed carrying the reason.