Bulk SMS
One request, up to 10,000 recipients, personalized and sent in the background.
Send a batch
curl -X POST "https://api.nopexo.com/v1/sms/bulk" \
-H "Authorization: Bearer $NOPEXO_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{
"from": "NOPEXO",
"body": "Hi {{first_name}}, your appointment is on {{date}}.",
"name": "November reminders",
"recipients": [
{
"to": "0200000009",
"fields": {
"first_name": "Ama",
"date": "12 Nov"
}
},
{
"to": "0241234567",
"fields": {
"first_name": "Kofi",
"date": "13 Nov"
}
}
]
}'- Use
tofor a plain list of numbers,recipientsfor numbers with personalizationfields, or both. - Placeholders like
{{first_name}}are filled from each recipient’s fields. Add a fallback with{{first_name|there}}. A recipient missing a required value is skipped rather than sent a message with a gap. - Add
scheduledAt(ISO 8601, 1 minute to 90 days ahead) to send later. - Use an
Idempotency-Key: repeating the request returns the same batch.
What gets skipped
Nopexo prepares the batch before anything is sent, and reports what it removed:
| Reason | Meaning |
|---|---|
| invalid | Not a valid Ghana mobile number, or too long after personalization. |
| duplicate | The same number appears more than once; it gets one message. |
| suppressed | The number opted out of your messages. |
| missing_data | A placeholder had no value and no fallback. |
| no_funds | Your wallet ran out partway through (production). |
Production batches check your wallet before starting; each message’s price is held as it’s queued and taken when the network accepts it. Bulk traffic uses its own rate-limited queue, so it never delays your single messages or OTP codes.
Follow progress
curl -X GET "https://api.nopexo.com/v1/sms/bulk/cmp_3vb8n2k5q7w1x9z4" \
-H "Authorization: Bearer $NOPEXO_API_KEY"Or receive bulk.completed when every message has been handed to the network, plus message.* events per message. For per-message results use GET /v1/sms/reports?batchId=….