eSMS AfricaeSMS Africa
SDKs

Python

Official Python SDK for the eSMS Africa SMS API.

The esms-sms package is fully typed with no required dependencies (standard library only). Requires Python 3.8+.

Install

pip install esms-sms

Quickstart

send.py
from esms import Esms

esms = Esms(api_key="esms_live_...")

res = esms.messages.send(
    to="+256700000000",
    text="Your verification code is 123456",
    sender_id="eSMSAfrica",  # optional — falls back to the route default
)

print(res.id, res.status)  # "...", "submitted"

Get an API key in the dashboard under Developers → API Keys.

Sending

# Auto-detects the route (country) from the number.
esms.messages.send(to="+254711000000", text="Hi from Kenya")

# Or pin a route explicitly.
esms.messages.send(to="+256700000000", text="Hi", route="ESMS_UG")

# Schedule for later (5 minutes to 7 days out).
from datetime import datetime, timedelta, timezone
esms.messages.schedule(
    to="+256700000000",
    text="Reminder",
    scheduled_at=datetime.now(timezone.utc) + timedelta(hours=1),
)

Delivery status

msg = esms.messages.get(res.id)
print(msg.status)  # queued | submitted | delivered | failed | ...
for event in msg.timeline:
    print(event.at, event.event, event.detail)

# List recent messages
page = esms.messages.list(limit=20, status="delivered")
print(page.total, len(page.messages))

# Retry a failed one
esms.messages.retry(res.id)

Balance & routes

bal = esms.balance.get()
print(f"{bal.currency} {bal.balance} (~{bal.sms_estimate} SMS left)")

for r in esms.routes.list():
    print(r.code, r.country_name, f"{r.currency} {r.price_per_segment}/segment")

Error handling

Every failure is an EsmsError. Catch specific subclasses to branch:

from esms import (
    InsufficientBalanceError,
    AuthenticationError,
    EsmsError,
)

try:
    esms.messages.send(to="+256700000000", text="Hi")
except InsufficientBalanceError as e:
    print(f"Top up: have {e.balance}, need {e.cost} {e.currency}")
except AuthenticationError:
    print("Check your API key.")
except EsmsError as e:
    print(f"{e.status} {e.code}: {e.message}")
ClassWhen
AuthenticationError401 — key missing or invalid
PermissionDenied403 — not allowed
NotFoundError404 — no such message
InvalidRequestError400 / 422 — bad request
InsufficientBalanceError422 — not enough credit (.balance, .cost, .currency)
RateLimitError429 — slow down
ApiError5xx — server error
EsmsConnectionErrornetwork failure or timeout

Configuration

Esms(
    api_key="esms_live_...",
    base_url="https://sms.esmsafrica.io/api",  # default
    timeout=30.0,     # seconds
    max_retries=2,    # transient failures (network, 429, 5xx) with backoff
)

On this page