Send Bulk SMS
Send the same SMS message to up to 10,000 recipients in a single API call. Each recipient is queued independently — a failure for one number does not stop the others.
Endpoint
POST /v1/sms/send-bulk/Authentication: Bearer API key
Request Body
{
"recipients": ["254712345678", "254723456789", "254734567890"],
"message": "Hi! Your invoice is ready. Log in to view it.",
"sender_id": "TALKNTALK"
}| Field | Type | Required | Description |
|---|---|---|---|
recipients | string[] | Yes | Array of phone numbers in international format. Duplicates are removed automatically. Max 10,000. |
message | string | Yes | SMS body sent to every recipient |
sender_id | string | No | Sender name. Defaults to your organisation's default sender ID. |
Request
curl -X POST https://api.talkntalk.africa/v1/sms/send-bulk/ \
-H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"recipients": ["254712345678", "254723456789"],
"message": "Your promo code is SAVE20. Valid today only!",
"sender_id": "TALKNTALK"
}'Response
201 Created — all messages queued successfully
207 Multi-Status — some messages failed (e.g. insufficient balance)
{
"queued": 2,
"failed": 1,
"total": 3,
"sender_id": "TALKNTALK",
"results": [
{ "id": "018f3a2b-...", "mobile": "254712345678", "status": "queued" },
{ "id": "018f3a2c-...", "mobile": "254723456789", "status": "queued" }
],
"errors": [
{ "mobile": "254734567890", "error": "insufficient_balance", "detail": "Insufficient balance. Required KES 1.00, available KES 0.00." }
]
}| Field | Description |
|---|---|
queued | Number of messages successfully queued |
failed | Number that could not be sent |
total | Total unique recipients after deduplication |
results | Per-number success list with message id and status |
errors | Per-number failure list with error code and detail |
Balance exhaustion behaviour
If the wallet runs out of funds mid-batch, processing stops immediately. All remaining recipients are marked skipped:
{ "mobile": "254799999999", "error": "skipped", "detail": "Processing stopped due to insufficient balance." }Code Examples
Node.js
const res = await fetch('https://api.talkntalk.africa/v1/sms/send-bulk/', {
method: 'POST',
headers: {
'Authorization': 'Bearer tk_live_xxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
recipients: ['254712345678', '254723456789', '254734567890'],
message: 'Your promo code is SAVE20!',
sender_id: 'TALKNTALK',
}),
});
const data = await res.json();
console.log(`Queued: ${data.queued}/${data.total}`);
data.errors.forEach(e => console.warn(`Failed: ${e.mobile} — ${e.detail}`));Python
import requests
recipients = ['254712345678', '254723456789', '254734567890']
r = requests.post(
'https://api.talkntalk.africa/v1/sms/send-bulk/',
headers={'Authorization': 'Bearer tk_live_xxxx'},
json={
'recipients': recipients,
'message': 'Your promo code is SAVE20!',
'sender_id': 'TALKNTALK',
},
)
data = r.json()
print(f"Queued: {data['queued']}/{data['total']}")
for err in data.get('errors', []):
print(f"Failed {err['mobile']}: {err['detail']}")PHP
$recipients = ['254712345678', '254723456789'];
$ch = curl_init('https://api.talkntalk.africa/v1/sms/send-bulk/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer tk_live_xxxx',
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode([
'recipients' => $recipients,
'message' => 'Your promo code is SAVE20!',
'sender_id' => 'TALKNTALK',
]),
]);
$data = json_decode(curl_exec($ch), true);
echo "Queued: {$data['queued']}/{$data['total']}\n";Tracking your campaign
Use the campaign_id returned in the response to monitor delivery:
| What you need | Endpoint |
|---|---|
| Overall progress (sent, failed, delivery rate) | Campaign Status |
| Per-recipient delivery status | Campaign Messages |
Rate Limits
This endpoint is limited to 60 requests per minute per organisation. Each call can contain up to 10,000 recipients, so this is rarely a bottleneck. See Rate Limits for details.
Error Responses
| Status | Code | Description |
|---|---|---|
400 Bad Request | — | recipients is empty, exceeds 10,000, or message is missing |
401 Unauthorized | authentication_failed | Missing or invalid API key |
207 Multi-Status | — | Partial success — check errors array |
429 Too Many Requests | — | Rate limit exceeded — retry after the Retry-After header |