SendAfrica logoSendAfricaDocs

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

POST/v1/sms/API Key
FieldTypeRequiredDescription
tostringYesRecipient — 0712345678 or +255712345678
messagestringYesSMS text (billed per 160/70-char part)
fromstringNoYour 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.

single.sh
bash
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"
  }'
200 OK
json
{
  "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-Key to make retries safe — successful sends are cached 24 h and replayed with Idempotent-Replay: true.

#Error responses

json
json
{ "error": { "code": "insufficient_credits", "message": "Insufficient credits to send SMS" } }
{ "error": { "code": "invalid_phone", "message": "+1234 is not a Tanzania number" } }

#Send bulk SMS

POST/v1/sms/bulkAPI Key or JWT

One 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.

bulk.sh
bash
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!"
  }'
200 OK — even with partial failures
json
{
  "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

bulk.py
python
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"])