Skip to Content

SMS

The client.sms resource handles single sends, client-side send-many, server-side bulk, message logs, and local message analysis.

Send a single message

Phone numbers are normalized to E.164 automatically; invalid numbers raise InvalidPhoneError before any network call:

result = client.sms.send( to="0712345678", message="Welcome to SendAfrica!", sender="SENDAFRICA", # optional registered sender ID ) print(result.message_id, result.credits_used)
ParameterTypeRequiredNotes
tostringYesAccepted formats: 0712345678, 255..., +255...
messagestringYesRequired
senderstringNoRegistered sender ID; omits from from the payload when absent

Returns an SMSResult dataclass: message_id, status, credits_used, cost, to.

Send many (client-side, paced)

N distinct messages, rate limited, with per-message failure collection instead of aborting on the first error:

results = client.sms.send_many( messages=[ {"to": "0712345678", "message": "Hi Ali"}, {"to": "0765432109", "message": "Hi Zainab"}, ], rate_limit_per_sec=10.0, # default 10 sender="MYBRAND", # applied to all unless per-message overrides ) print(results.sent_count, results.failed_count) for r in results.results: print(r.message_id, r.to) for f in results.failed: print(f["index"], f["to"], f["error"])

Use this when your recipients each need a different message. For the same message to many numbers, prefer server-side bulk below.

Server-side bulk SMS

Send one message to many recipients in a single API call. The SDK caps at 100 recipients; the server returns partial failures per recipient and refunds them individually.

bulk = client.sms.bulk( to=["0712345678", "0765432109"], message="Black Friday starts now!", sender="MYBRAND", ) print(bulk.total, bulk.sent, bulk.failed) for r in bulk.results: print(r.to, r.status, r.message_id, r.error)

The returned BulkSendResult exposes total, sent, failed, and results (per-recipient to, status, message_id, credits_used, error).

Message logs

logs = client.sms.logs( page=1, per_page=25, status="delivered", # pending | sent | delivered | failed search="0712345678", date_from="2026-09-01T00:00:00Z", ) print(logs.total, logs.page, logs.total_pages) for entry in logs.items: print(entry.to_phone, entry.status, entry.credits_used, entry.sent_at)

Client-side SMS analysis

Analyze a message locally — no network call — to predict encoding, part count, and credits:

analysis = client.sms.analyze("Hello world from SendAfrica 🇹🇿") print(analysis.encoding, analysis.parts, analysis.credits) # UCS-2 1 1 (emoji forces Unicode encoding)

Returns an SMSAnalysis dataclass: encoding (“GSM-7” or “UCS-2”), characters, septets, parts, credits.

Reference

MethodEndpointReturns
sms.send(to, message, *, sender)POST /smsSMSResult
sms.send_many(messages, *, sender, rate_limit_per_sec)Loops POST /smsBulkSMSResult
sms.bulk(to, message, *, sender)POST /sms/bulkBulkSendResult
sms.logs(page, per_page, status, search, date_from)GET /sms/logsMessageLogListResponse
sms.analyze(message)— (local)SMSAnalysis

Delivery confirmation is asynchronous — see Webhooks and Delivery Status.

Last updated on