Skip to main content

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

Project description

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.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

kenya_sms-1.0.0.tar.gz (8.8 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

kenya_sms-1.0.0-py3-none-any.whl (8.0 kB view details)

Uploaded Python 3

File details

Details for the file kenya_sms-1.0.0.tar.gz.

File metadata

  • Download URL: kenya_sms-1.0.0.tar.gz
  • Upload date:
  • Size: 8.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for kenya_sms-1.0.0.tar.gz
Algorithm Hash digest
SHA256 0a4da3cb9e1481132fbb543aa5f21baf6d511daf1bc403936197d8e88f4804ab
MD5 a2c6b506a3a19d84a560b10bf4dad5da
BLAKE2b-256 6fc4687e1b5a78691bb7f0977605084d809453ac383bedbb0ed09d85b8c8521a

See more details on using hashes here.

Provenance

The following attestation bundles were made for kenya_sms-1.0.0.tar.gz:

Publisher: publish.yml on gabrielmahia/kenya-sms

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file kenya_sms-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: kenya_sms-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 8.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for kenya_sms-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 2e0a80aa2e8b3d20769e709aa0c3f96e9e35c5597f4f983e1461bb652cdc3e75
MD5 edae8ed46ef7492b4563d0d66607208d
BLAKE2b-256 70593a224f3e72e9ce03c5e4b7dcab90cc09cdfb099198375ddf350e83898648

See more details on using hashes here.

Provenance

The following attestation bundles were made for kenya_sms-1.0.0-py3-none-any.whl:

Publisher: publish.yml on gabrielmahia/kenya-sms

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page