v1.0.0 — Now on PyPI

Send SMS in
Tanzania
with one line.

A clean, typed, zero-fuss Python SDK for the messaging-service.co.tz API v2. Built for developers who want to ship fast and sleep soundly.

$ pip install pynextsms
3.8+
Python Support
1
Dependency
45
Tests
95%
Coverage
MIT
License

Everything you need.
Nothing you don't.

Designed to be intuitive on day one and maintainable for years.

📤

Single & Broadcast

Send to one number or a thousand with the exact same API call. The SDK handles the routing.

🎯

Personalised Bulk

Different messages to different people in one HTTP call via send_bulk().

🕐

Scheduling

Schedule one-time or recurring SMS — hourly, daily, weekly, or monthly — with a clean dataclass API.

🔁

Auto Retry

Transient 5xx errors are retried automatically with exponential back-off. No extra code needed.

🛡️

Typed Responses

Every response is a typed dataclass — no raw dict wrangling. Full mypy strict support included.

🔑

12-Factor Ready

Credentials from env vars (PYNEXTSMS_TOKEN) out of the box. Docker and CI friendly.

Simple by design.

Four methods. Consistent signatures. No surprises.

Send SMS
Broadcast
Bulk
Schedule
Error Handling
send_single.py
from pynextsms import SMSClient

client = SMSClient(
    token="your_bearer_token",
    sender_id="RMNDR",
)

# Send to a single recipient
resp = client.sms.send(
    to="255763930052",
    text="Hello, Ronald! Welcome aboard.",
    reference="onboard_001",   # optional
)

if resp.successful:
    print(f"✓ Sent! id={resp.message_id}")
else:
    print(f"✗ Failed: {resp.raw}")
broadcast.py
from pynextsms import SMSClient

with SMSClient(token="your_token", sender_id="BRAND") as client:

    # Same message → many recipients in ONE API call
    resp = client.sms.send(
        to=[
            "255712345678",
            "255686123903",
            "255767245612",
        ],
        text="Hello subscribers — June sale starts now!",
        reference="june_promo",
    )

    print(f"Broadcast sent: {resp.successful}")
send_bulk.py
from pynextsms import SMSClient, MessageRecipient

with SMSClient(token="your_token", sender_id="BRAND") as client:

    # Different message per recipient — still ONE API call
    resp = client.sms.send_bulk(
        messages=[
            MessageRecipient("255763930052", "Hello Precious, welcome!"),
            MessageRecipient("255627350020", "Hello Patricia, welcome!"),
            MessageRecipient("255773930052", "Hello Daniel, welcome!"),
        ],
        reference="onboarding_batch_001",
    )

    print(f"Sent {resp.total} personalised messages")
schedule.py
from datetime import date, time
from pynextsms import SMSClient, ScheduleOptions, RepeatInterval

with SMSClient(token="your_token", sender_id="BRAND") as client:

    opts = ScheduleOptions(
        send_date  = date(2025, 6, 1),
        send_time  = time(9, 0),         # 09:00 AM
        repeat     = RepeatInterval.DAILY,
        end_date   = date(2025, 6, 30),
    )

    resp = client.sms.schedule(
        to      = "255763930052",
        text    = "Good morning! Check your dashboard.",
        options = opts,
    )

    print(f"Scheduled: {resp.successful} ref={resp.reference}")
error_handling.py
from pynextsms import (
    SMSClient,
    AuthenticationError,
    ValidationError,
    RateLimitError,
    APIError,
)

client = SMSClient(token="your_token", sender_id="RMNDR")

try:
    resp = client.sms.send("255763930052", "Hello!")

except AuthenticationError:
    print("Bad token — check PYNEXTSMS_TOKEN")

except ValidationError as e:
    print(f"Bad input: {e}")    # caught before HTTP

except RateLimitError as e:
    print(f"Slow down — retry in {e.retry_after}s")

except APIError as e:
    print(f"API error HTTP {e.status_code}: {e}")

The full surface area.

Three methods. Every parameter documented.

client.sms.send()

send(to, text, *, sender_id, flash, reference)

Send one message to one or many recipients. Pass a list for broadcast.

  • to str | list[str] required
  • text str required
  • sender_id str | None — overrides default
  • flash bool — Class-0 SMS. Default False
  • reference str | None — auto-generated if omitted
client.sms.send_bulk()

send_bulk(messages, *, flash, reference)

Send different messages to different recipients in a single API call.

  • messages list[MessageRecipient] required
  • flash bool — Default False
  • reference str | None — batch tracking ref
client.sms.schedule()

schedule(to, text, options, *, sender_id, reference)

Schedule a one-time or recurring SMS for a future date and time.

  • to str required
  • text str required
  • options ScheduleOptions required
  • sender_id str | None
  • reference str | None
ScheduleOptions

ScheduleOptions(send_date, send_time, repeat, ...)

Dataclass controlling when (and how often) a scheduled SMS fires.

  • send_date date required
  • send_time time required
  • repeat RepeatInterval | None
  • start_date date | None
  • end_date date | None
Exception HTTP When raised
AuthenticationError 401 Token is missing, expired, or rejected by the API
ValidationError Bad input caught before any HTTP request is made
RateLimitError 429 Too many requests. Check .retry_after attribute
APIError 4xx/5xx Any other non-2xx API response. Check .status_code
PyNextSMSError Base class — catch this to handle all SDK errors in one block

Up and running
in 60 seconds.

No configuration files. No boilerplate. Just install and go.

1
Install the package

Requires Python 3.8+ and pip.

pip install pynextsms
2
Set your credentials

Get your Bearer Token from the messaging-service.co.tz dashboard.

export PYNEXTSMS_TOKEN="your_bearer_token" export PYNEXTSMS_SENDER_ID="YOURBRAND"
3
Send your first SMS

That's it — no config files, no boilerplate.

python -c " from pynextsms import SMSClient client = SMSClient() resp = client.sms.send('255763930052', 'Hello!') print(resp) "
4
Explore further

Read the full source, report issues, or contribute on GitHub.

https://github.com/ronaldgosso/pynextsms