Skip to content
Sendozi

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.

By SendoziUpdated 3 min read

Before you start

  • A Sendozi account, with email and phone verified at signup.
  • KYC approval. API keys, sandbox and live, can be created only once your business verification is approved in the Console.
  • A role that can manage the API: the workspace owner, an administrator or a developer.
  • For live sends only: an approved Sender ID and a funded wallet.

1. Create a sandbox key

In the Console, open Developers > API keys and create a key in sandbox mode. The secret, starting sk_test_, is shown once. Sendozi stores only a hash of it, so copy it into an environment variable straight away.

Keep the key out of your code
Shell
export SENDOZI_API_KEY="sk_test_..."

Check the key with GET /v1/me. It returns the workspace and the key's mode and scopes, and sends nothing.

GET /v1/me
cURL
curl https://api.sendozi.com/v1/me \
  -H "Authorization: Bearer $SENDOZI_API_KEY"

2. Send a message

A promotional send is the simplest first request: one recipient, a message and the route. In sandbox nothing is delivered and nothing is charged.

POST /v1/sms/send
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: quickstart-001" \
  -d '{
    "sender": "YourBrand",
    "recipient": "08012345678",
    "message": "Welcome to Acme. Your account is ready.",
    "route": "promotional"
  }'
Node.js
const response = await fetch("https://api.sendozi.com/v1/sms/send", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.SENDOZI_API_KEY}`,
    "Content-Type": "application/json",
    "Idempotency-Key": "quickstart-001",
  },
  body: JSON.stringify({
    sender: "YourBrand",
    recipient: "08012345678",
    message: "Welcome to Acme. Your account is ready.",
    route: "promotional",
  }),
});

const body = await response.json();
if (!body.success) throw new Error(`${body.error.code}: ${body.error.message}`);
console.log(body.data.batch_id, body.data.message_id);
Python
import os
import httpx

response = httpx.post(
    "https://api.sendozi.com/v1/sms/send",
    headers={
        "Authorization": f"Bearer {os.environ['SENDOZI_API_KEY']}",
        "Idempotency-Key": "quickstart-001",
    },
    json={
        "sender": "YourBrand",
        "recipient": "08012345678",
        "message": "Welcome to Acme. Your account is ready.",
        "route": "promotional",
    },
    timeout=30.0,
)

body = response.json()
if not body["success"]:
    raise RuntimeError(f"{body['error']['code']}: {body['error']['message']}")
print(body["data"]["batch_id"], body["data"].get("message_id"))

3. Read the response

A send is accepted into a queue and answered with 202 Accepted. The response describes the batch it created, not a delivery: the message goes to the network moments later.

202 Accepted
JSON
{
  "success": true,
  "data": {
    "batch_id": "bat_5f45b8c07bd844c8",
    "channel": "sms",
    "mode": "sandbox",
    "status": "queued",
    "requested_count": 1,
    "accepted_count": 1,
    "duplicates_removed": 0,
    "invalid_count": 0,
    "suppressed_count": 0,
    "dnd_skipped_count": 0,
    "consent_rejected_count": 0,
    "estimated_cost_kobo": 700,
    "reserved_cost_kobo": 0,
    "progress": { "queued": 1, "processing": 0, "sent": 0, "delivered": 0, "failed": 0, "skipped": 0 },
    "message_id": "msg_7c1e0f9a2b3d4e5f",
    "type": "single"
  },
  "request_id": "req_ad1550371bbdaf92"
}
  • message_id is present when exactly one recipient was accepted. For a send to several recipients, list them with GET /v1/message-batches/{batch_id}/recipients.
  • estimated_cost_kobo is what the send costs live. In sandbox it is reported and reserved_cost_kobo is 0, because nothing is reserved or charged.
  • request_id is also returned in the x-request-id header. Log it; it is how a request is traced.

4. Follow it to delivery

Look the message up by its id. Its status starts at queued, becomes accepted when it is handed to the network, and ends at delivered, failed or expired. A sandbox message stops at accepted, because nothing is sent to a network.

GET /v1/messages/{id}
cURL
curl https://api.sendozi.com/v1/messages/msg_7c1e0f9a2b3d4e5f \
  -H "Authorization: Bearer $SENDOZI_API_KEY"

Rather than polling, register a webhook for message.delivered and message.failed, and Sendozi posts each outcome to you.

5. Go live

  1. 1

    Get a Sender ID approved

    Request it in the Console under Sender IDs, for the route you will send on. Until it is approved, a live send returns sender_id_not_approved.

  2. 2

    Fund the wallet

    A live send reserves its estimated cost when it is accepted. Without the balance it returns insufficient_balance and nothing is queued.

  3. 3

    Create a live key

    Create a production key under Developers > API keys. It starts sk_live_.

  4. 4

    Swap the key

    Change the environment variable. The base URL, endpoints and request bodies stay the same.

  5. 5

    Send one message to your own phone

    Confirm it arrives and that your webhook receives message.delivered.

Frequently asked questions

Do I need an SDK to use the Sendozi API?
No, and there is no official SDK. Every endpoint is a plain HTTPS request with a JSON body, so the HTTP client already in your project is enough.
Why can I not create an API key yet?
API keys, including sandbox keys, can be created only after your business verification (KYC) is approved. Submit it in the Console under KYC verification.
Why does my sandbox message stay accepted?
Sandbox records the send but never hands it to a network, so there is no delivery report to move it on. accepted is the final status of a sandbox message.
What is the base URL?
https://api.sendozi.com/v1. GET /v1 returns an index of every public route.

Create your account

Sign up, complete KYC, and create a sandbox key to start integrating.