Send SMS
Send single and bulk SMS via the REST API — request bodies, sender IDs, idempotency, partial-failure semantics, and error handling.
Use an API key
Use API key authentication for all SMS sending from your application. JWT auth is for the dashboard only.
#Send a single SMS
/v1/sms/API Key| Field | Type | Required | Description |
|---|---|---|---|
to | string | Yes | Recipient — 0712345678 or +255712345678 |
message | string | Yes | SMS text (billed per 160/70-char part) |
from | string | No | Your registered sender ID (max 11 chars). Omit to use the platform default SendAfrika. |
Only registered sender IDs are honored
Omitting from sends from the platform default SendAfrika. Passing an unregistered or unauthorized sender ID doesn't fail the request — the carrier rejects it and SendAfrica automatically re-sends your message under its fallback sender, so your branding is silently lost. Register a sender ID before using it here — see Sender IDs.
curl -s -X POST https://api.sendafrica.online/v1/sms/ \
-H "X-API-Key: $SENDAFRICA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": "0712345678",
"message": "Your OTP is 482910. It expires in 5 minutes.",
"from": "MyBrand"
}'{
"success": true,
"data": {
"message_id": "SA-f3b1c2d49e8a4f2bb1c2d3e4f5a6b7c8",
"status": "sent",
"cost": "TZS 35.00",
"credits_used": 1
}
}- Credits are deducted before sending; gateway rejections are refunded automatically.
- Every send is logged to your message history (
GET /v1/sms/logs). - Pass
Idempotency-Keyto make retries safe — successful sends are cached 24 h and replayed withIdempotent-Replay: true.
#Error responses
{ "error": { "code": "insufficient_credits", "message": "Insufficient credits to send SMS" } }
{ "error": { "code": "invalid_phone", "message": "+1234 is not a Tanzania number" } }#Send bulk SMS
/v1/sms/bulkAPI Key or JWTOne message to many recipients in a single call — capped at 100 recipients. For larger audiences, create a Campaign instead so per-recipient tracking stays correct.
curl -s -X POST https://api.sendafrica.online/v1/sms/bulk \
-H "X-API-Key: $SENDAFRICA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"to": ["0712345678", "0754000111"],
"message": "Flash sale today only!"
}'{
"success": true,
"data": {
"total": 2,
"sent": 1,
"failed": 1,
"results": [
{ "to": "+255712345678", "status": "sent", "message_id": "SA-...", "credits_used": 1 },
{ "to": "+255754000111", "status": "failed", "error": "invalid_phone_number" }
]
}
}Always 200
Bulk responses return HTTP 200 even with failures — check data.sent / data.failed, never just the status code. Each failure is collected individually; one bad number never aborts the batch.
#Dashboard equivalents
POST /v1/sms/send and POST /v1/sms/bulk accept JWT auth for dashboard-session sending. The developer routes above are identical in behavior but require an API key.
#SDK bulk helpers
results = client.sms.send_many([
{"to": "0711111111", "message": "Hello John"},
{"to": "0722222222", "message": "Hello Mary"},
{"to": "+255733333333", "message": "Hello Alex"},
], sender="MyBrand")
print(results.sent_count) # 2
print(results.failed_count) # 1
for failure in results.failed:
print(failure["index"], failure["to"], failure["error"])