Skip to main content

kenya-sms

Africa's Talking SMS wrapper for Kenya — bilingual templates, delivery tracking, bulk sending.

CI Python Tests Zero deps License

SMS is the primary notification channel for Kenya. This library wraps the Africa's Talking API with the patterns that production Kenya systems actually need: bilingual English/Kiswahili templates, phone number normalisation, delivery receipt tracking, rate-limit backoff, and bulk broadcast sending.


Install

pip install kenya-sms

Quickstart

from kenya_sms import SMSClient, Templates, Language

client = SMSClient(
    api_key="your_at_api_key",
    username="your_at_username",
    sender_id="MYAPP",      # Registered with Communications Authority of Kenya
)

# Single message — phone normalised automatically
result = client.send("0712345678", "Your order is confirmed.")
print(result.succeeded, result.cost)  # True, "KES 1.0000"

# Bilingual template — user's language preference
result = client.send_template(
    "254712345678",
    Templates.CONTRIBUTION_RECEIVED,
    language=Language.KISWAHILI,
    name="Jane", amount="2,000", cycle="January", receipt="NLJ7RT61SV",
)
# → "Habari Jane, mchango wako wa KES 2,000 kwa January umepokelewa. Risiti: NLJ7RT61SV."

Bilingual templates

All templates render in English or Kiswahili with the same variables:

from kenya_sms import Template, Language

# Built-in templates
Templates.CONTRIBUTION_RECEIVED   # Chama contribution confirmed
Templates.CONTRIBUTION_REMINDER   # Upcoming contribution due
Templates.LOAN_APPROVED           # Loan disbursement notice
Templates.DROUGHT_ALERT           # OpenResilience early warning
Templates.PAYMENT_PROMPT          # M-Pesa payment instructions
Templates.OTP                     # Verification code

# Custom template
tpl = Template(
    en="Dear {name}, your loan repayment of KES {amount} is due on {date}.",
    sw="Habari {name}, malipo yako ya mkopo ya KES {amount} yanastahili tarehe {date}.",
)
msg = tpl.render(Language.KISWAHILI, name="John", amount="4,333", date="31 Jan")
parts = tpl.sms_parts(Language.KISWAHILI, name="John", amount="4,333", date="31 Jan")
# → 1 part (within 160 chars)

Phone number normalisation

Accepts any Kenyan format:

from kenya_sms import normalise_phone

normalise_phone("0712345678")      # → "254712345678"
normalise_phone("+254712345678")   # → "254712345678"
normalise_phone("712345678")       # → "254712345678"
normalise_phone("0112345678")      # → "254112345678"  (Safaricom Home)

Bulk sending

# Different message per recipient
results = client.send_bulk([
    ("0712345678", "Your contribution for January is confirmed."),
    ("0723456789", "Mchango wako wa Januari umethibitishwa."),
    ("0734567890", "Your contribution is pending. Please pay by Friday."),
])

# Same message to many — uses AT's batch endpoint
results = client.send_broadcast(
    phones=["0712345678", "0723456789", "0734567890"],
    message="Chama meeting Saturday 10am at the usual venue.",
)
successful = [r for r in results if r.succeeded]

Delivery tracking

# Mount at your AT delivery report callback URL
@app.post("/sms/delivery")
async def delivery_report(request: Request):
    payload = await request.json()
    receipt = client.handle_delivery_receipt(payload)
    return {"status": "ok"}

# Query later
store = client.delivery_store
failed = store.failed()  # Messages that did not deliver
print(f"{len(failed)} undelivered messages")

Sandbox mode

client = SMSClient(
    api_key="sandbox",
    username="sandbox",
    sandbox=True,   # Routes to AT sandbox — no real SMS sent
)

Use with OpenResilience

from kenya_sms import SMSClient, Templates, Language
from kenya_counties import get

# Send drought alert to all Turkana subscribers
turkana = get("Turkana")
client = SMSClient(api_key=AT_KEY, username=AT_USER, sender_id="RESILIENCE")

for subscriber_phone in get_turkana_subscribers():
    client.send_template(
        subscriber_phone,
        Templates.DROUGHT_ALERT,
        Language.KISWAHILI,
        county=turkana.name,
        level="Kali",
        deficit="48",
        action="kuvuna mapema",
    )

Design decisions

Zero runtime dependencies. The Africa's Talking API is a simple REST + form-encoded endpoint. urllib.request handles it without httpx or requests.

Template-first design. In production Kenya systems, the same message goes out in both languages constantly. Encoding this as a first-class type — not a function or a string — means templates are testable, reusable, and auditable.

Phone normalisation is non-negotiable. Kenyan users enter phone numbers in at least four different formats. Failing on anything other than E.164 means real users get dropped. The normaliser accepts all common formats and rejects genuinely invalid input.


Part of the nairobi-stack East Africa engineering ecosystem. Maintained by Gabriel Mahia. Kenya × USA.

Metadata

Release files for kenya-sms 1.0.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for kenya-sms 1.0.1
File Size Uploaded Provenance Actions
kenya_sms-1.0.1.tar.gz 8.9 kB With provenance Details for kenya_sms-1.0.1.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for kenya-sms 1.0.1
File Interpreter ABI Platform Actions
kenya_sms-1.0.1-py3-none-any.whl Python 3 none any Details for kenya_sms-1.0.1-py3-none-any.whl

Total release size: 16.9 kB

Release files / kenya_sms-1.0.1.tar.gz

Download URL kenya_sms-1.0.1.tar.gz
Size 8.9 kB
Tags Source
SHA-256 checksum
How to use checksums
d8ba43b65bfe42e348e909cbd95bcd823ac4e18a6df196a9dc0d49e1dbcb8a3d
BLAKE2b-256 checksum
How to use checksums
8e564ab0a00b2750fbd6cc1b13ad3764e562fe727583901369cb72fd8e876d3b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.

Transparency log

Release files / kenya_sms-1.0.1-py3-none-any.whl

Download URL kenya_sms-1.0.1-py3-none-any.whl
Size 8.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8c7bf9569add9426d548eba4edcb3a6b4b2fbbd837b0b24cf4c8cc430896441c
BLAKE2b-256 checksum
How to use checksums
50d66fabcfe9fd520e0206343fd616dff637f12840b97ef27f72052d7b9c3596
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.

Transparency log

Security for kenya-sms 1.0.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 2 files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for kenya_sms-1.0.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 21, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

1.0.1 This release

2 release files Full provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page