Campaign Messages
Fetch the per-recipient delivery status for every message in a bulk SMS campaign. Use this to see exactly which numbers were delivered, failed, or are still pending.
Endpoint
POST /v1/sms/campaigns/messages/Authentication: Bearer API key
Request Body
{
"campaign_id": "44210c48-5ba9-4784-b434-dd57bf1d2b46",
"status": "failed",
"page": 1,
"page_size": 100
}| Field | Type | Required | Description |
|---|---|---|---|
campaign_id | UUID string | Yes | The campaign_id returned when you sent the bulk campaign |
status | string | No | Filter by recipient status: queued, sent, failed. Omit to return all. |
page | integer | No | Page number (default: 1) |
page_size | integer | No | Results per page (default: 100, max: 1000) |
Request
curl -X POST https://api.talkntalk.africa/v1/sms/campaigns/messages/ \
-H "Authorization: Bearer tk_live_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" \
-H "Content-Type: application/json" \
-d '{
"campaign_id": "44210c48-5ba9-4784-b434-dd57bf1d2b46",
"page_size": 50
}'Response
200 OK
{
"campaign_id": "44210c48-5ba9-4784-b434-dd57bf1d2b46",
"campaign_status": "completed",
"recipients_count": 1248,
"sent_count": 1245,
"failed_count": 3,
"delivery_rate": 99.8,
"total": 1248,
"page": 1,
"page_size": 50,
"total_pages": 25,
"next": "https://api.talkntalk.africa/v1/sms/campaigns/messages/?page=2&page_size=50",
"previous": null,
"results": [
{
"mobile": "254712345678",
"status": "sent",
"message_id": "018f3a2b-7c4d-7e1a-b3f2-9d8e2c1a4b5f",
"message_status": "delivered",
"error": null,
"sent_at": "2026-05-20T11:01:14+03:00"
},
{
"mobile": "254799999999",
"status": "failed",
"message_id": "019a4b3c-8d5e-8f2b-c4a3-0e9f3d2b5c6g",
"message_status": "failed",
"error": "Number not reachable",
"sent_at": "2026-05-20T11:01:15+03:00"
}
]
}Top-level fields
| Field | Description |
|---|---|
campaign_id | UUID of the campaign |
campaign_status | Overall campaign state (queued, running, completed, failed) |
recipients_count | Total recipients |
sent_count | Successfully dispatched |
failed_count | Failed to send |
delivery_rate | Percentage delivered |
total | Total rows matching the filter |
next / previous | Pagination URLs |
Per-recipient fields (results[])
| Field | Description |
|---|---|
mobile | Recipient phone number |
status | Campaign dispatch status: queued / sent / failed |
message_id | UUID of the individual SMS — use with Fetch Messages for more detail |
message_status | Provider delivery status: queued → sent → delivered / failed / undelivered |
error | Error description if message_status is failed, otherwise null |
sent_at | Timestamp of the last status update |
statusvsmessage_status:statustells you whether the campaign worker dispatched the number.message_statusis the real delivery confirmation from the network — this is the field to watch.
Code Examples
Fetch all failed recipients
// Node.js
const res = await fetch('https://api.talkntalk.africa/v1/sms/campaigns/messages/', {
method: 'POST',
headers: { 'Authorization': 'Bearer tk_live_xxxx', 'Content-Type': 'application/json' },
body: JSON.stringify({
campaign_id: '44210c48-5ba9-4784-b434-dd57bf1d2b46',
status: 'failed',
page_size: 1000,
}),
});
const data = await res.json();
console.log(`Failed: ${data.failed_count}`);
data.results.forEach(r => console.log(r.mobile, '—', r.error));# Python — iterate all pages
import requests
API_KEY = 'tk_live_xxxx'
CAMPAIGN_ID = '44210c48-5ba9-4784-b434-dd57bf1d2b46'
page = 1
while True:
r = requests.post(
'https://api.talkntalk.africa/v1/sms/campaigns/messages/',
headers={'Authorization': f'Bearer {API_KEY}'},
json={'campaign_id': CAMPAIGN_ID, 'page': page, 'page_size': 500},
)
data = r.json()
for recipient in data['results']:
print(recipient['mobile'], recipient['message_status'])
if not data['next']:
break
page += 1Error Responses
| Status | Description |
|---|---|
400 Bad Request | campaign_id missing |
401 Unauthorized | Missing or invalid API key |
404 Not Found | Campaign not found or does not belong to your organisation |