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