Skip to content
Sendozi

DOCUMENTATION

Send your first SMS in a few minutes

The Sendozi API is plain HTTPS with JSON. There is no SDK to install and no separate sandbox host: the same endpoints serve test and live traffic, and the key prefix decides which.

Your first request. With a sk_test_ key nothing is sent or charged; swap in a sk_live_ key for production.
cURL
curl -X POST https://api.sendozi.com/v1/sms/send \
  -H "Authorization: Bearer $SENDOZI_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: first-send-001" \
  -d '{
    "sender": "YourBrand",
    "recipient": "08012345678",
    "message": "Welcome to Acme. Your account is ready.",
    "route": "promotional"
  }'
Base URL
https://api.sendozi.com
Version
v1
Auth
Bearer API key, or X-API-Key
Sandbox
sk_test_ keys, same endpoints
SMS rate
₦7.00 per page
Send rate limit
300/min per workspace
Max SMS length
1000 characters, 469 in Unicode
Recipients
Nigerian mobile numbers, 080… or +234…
Per request
up to 1,000,000 recipients

Getting started

  • Quickstart: send your first SMS

    Create a sk_test_ key in the Console, POST to /v1/sms/send with a sender, a recipient, a message and a route, and read back the queued batch. Follow the message_id to its delivery status, then swap to a sk_live_ key.

  • Authentication, API keys and scopes

    Send the API key as a bearer token. sk_test_ keys are sandbox and sk_live_ keys are production. Each key carries scopes that decide which endpoints it may call, and a key is shown once, stored as a hash, and replaced rather than recovered.

  • Sandbox testing

    A sk_test_ key runs requests through the same endpoints and the same request validation, records the message, and stops before sending or charging. It skips the account checks - Sender ID approval, KYC, wallet and the transactional limits - so a clean sandbox run is not proof a live send will pass.

Sending

  • Sending SMS

    POST /v1/sms/send or /v1/sms/bulk with a sender, one or more recipients, the message and a route. The send is queued and answered with 202 and a batch: invalid, repeated and opted-out numbers are removed and counted, the cost is reserved, and each recipient is charged as it is handed to the network.

  • Transactional SMS: OTPs, alerts and receipts

    Transactional SMS carries one person's own event - an OTP, a payment alert, a receipt. Each request has exactly one recipient and an Idempotency-Key, and the message is your own text: there are no templates to register or match.

  • Messages, batches and delivery status

    A send returns a batch_id. The batch holds one recipient per accepted number, and each recipient becomes a message with its own message_id. Look up either by id, page through recipients to see every number's outcome, and cancel a batch that is still queued or sending.

Reliability

  • Webhooks

    Register an HTTPS endpoint with POST /v1/webhooks/endpoints and Sendozi POSTs each event to it as JSON, signed with HMAC-SHA256 using a secret shown once at creation. A failed delivery is retried for about 46 hours, and an endpoint that keeps failing is paused with its events held until you resume it.

  • Idempotency and safe retries

    Send an Idempotency-Key header on POST /v1/sms/send and /v1/sms/bulk. A repeat with the same key and the identical body returns the original response and sends nothing. Keys belong to your workspace and last 24 hours. Transactional sends require one.

  • Errors and the response envelope

    Every response has success, then data or error, and a request_id. An error carries a stable code, a message and a resolution. 4xx codes are answers about your request and will repeat if resent unchanged; 429 and 5xx are worth retrying with the same Idempotency-Key.

  • Limits, large sends and pagination

    Send endpoints allow 300 requests a minute per workspace, and one request can carry up to 1,000,000 recipients. A send is accepted into a queue and handed to the networks at a steady rate, so a large campaign takes time to go out. Lists use cursor pagination.

Reference

  • Account, balance, usage and Sender IDs

    GET /v1/me identifies the key and its workspace, GET /v1/account/balance returns the wallet in kobo and naira, GET /v1/account/usage counts messages and spend for the key's mode, and GET /v1/sms/sender-ids lists Sender IDs with their route and status. None of them change anything.

Integrations

  • Send SMS with Node.js

    Node 18 and later include fetch, so no package is needed. The client below sends promotional and transactional SMS with an Idempotency-Key, throws a typed error carrying error.code, and pairs with a webhook receiver that verifies the timestamped signature.

  • Send SMS with Python

    There is no Sendozi Python SDK; httpx or requests is enough. The client below serialises each body once, retries network errors, 429 and 5xx with the same Idempotency-Key, and raises an error carrying error.code. The receivers verify the timestamped signature over the raw body.

  • Send SMS with PHP and Laravel

    There is no Sendozi PHP package. Plain PHP posts JSON with cURL; Laravel uses Http::withToken. Encode each body once, retry network errors, 429 and 5xx with the same Idempotency-Key, keep the key in config, and queue anything larger than a single OTP.

  • Sending SMS over SMPP

    Banks, fintechs and aggregators can send to Sendozi over SMPP 3.4 as well as the HTTP API. Sendozi creates the account; you bind from your allowed IPs with the system ID and password, send submit_sm with your approved Sender ID, and receive delivery receipts as deliver_sm on the same connection.

Channel availability

SMSLive
Bulk and transactional SMS to Nigerian numbers is live. Production sending opens once KYC is approved and a sender ID is registered.

Get a sandbox key

Sandbox runs the same validation as a live send, without calling a provider or debiting the wallet.