SendaiDocs

Guides

View as Markdown

Authentication

Authenticate to the Sendai SMS API with an API key sent as a bearer token — how to create one, keep it secret, rotate it, and revoke it.

Every request to the Sendai SMS API is authenticated with an API key, sent as a bearer token in the Authorization header:

Authorization: Bearer sk_live_4c8e…

There is nothing else to configure — no signing, no session to keep alive, no expiry to handle. A key is valid from the moment you create it until you revoke it.

Create a key

Create keys from the Settings → Developer tab in the dashboard, or over the API. Give each key a name that identifies the service using it — you will be glad of it when you come to rotate.

RequestPOST /api/v1/api-tokens
curl -X POST https://api.sendai.co.zw/api/v1/api-tokens \
  -H "Authorization: Bearer $SENDAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "orders-service" }'
Response
201 Created
{
  "status": "success",
  "message": "api token created — save this token, it will not be shown again",
  "data": {
    "id": "9f2a4c8e-6b21-4d0f-a97b-5e8c1d2f6a3b",
    "name": "orders-service",
    "token": "sk_live_4c8e6b21d0f34a97b5e8c1d2f6a3b904",
    "account_id": "2d6f4b8e-1a90-4e21-8b7d-3f1a5c2e9a0c",
    "created_at": "2026-07-06T09:12:03Z"
  }
}

data.id is what you pass to the revoke endpoint — keep it alongside the key. account_id tells you which account the key authenticates as.

token is returned exactly once. It appears in this create response and nowhere else — Sendai stores only a hash. Put it straight into your secret manager. If you lose it, you cannot recover it; revoke the key and create another.

Use it

Send the key as a bearer credential on every call:

RequestPOST /api/v1/sms
curl -X POST https://api.sendai.co.zw/api/v1/sms \
  -H "Authorization: Bearer $SENDAI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "to": "263771000000", "from": "YOUR_SENDER_ID", "message": "Your code is 4821" }'

A missing, malformed, or revoked key returns 401:

Response
401 Unauthorized
{
  "status": "error",
  "message": "missing authentication",
  "error": { "code": "UNAUTHORIZED", "description": "missing authentication" }
}

List your keys

Listing lets you audit which keys exist and what each is for:

RequestGET /api/v1/api-tokens
curl https://api.sendai.co.zw/api/v1/api-tokens \
  -H "Authorization: Bearer $SENDAI_API_KEY"
Response
200 OK
{
  "status": "success",
  "message": "",
  "data": [
    {
      "ID": "9f2a4c8e-6b21-4d0f-a97b-5e8c1d2f6a3b",
      "CreatedAt": "2026-07-06T09:12:03Z",
      "Name": "orders-service",
      "Active": true,
      "LastUsedAt": "2026-08-06T11:04:19Z"
    }
  ]
}

Field names on this endpoint are PascalCase, not snake_case like the rest of the API — it serialises the internal record directly. Read ID, Name, Active, CreatedAt and LastUsedAt; the response carries a few storage columns beyond these, which you should treat as unstable and not build against.

LastUsedAt is the useful one for cleanup: a key that has never been used is null, and a key untouched for months is usually one you can revoke.

Revoke a key

Revocation takes effect immediately — the next request using that key gets a 401. Pass the ID from the create or list response:

RequestDELETE /api/v1/api-tokens/{id}
curl -X DELETE https://api.sendai.co.zw/api/v1/api-tokens/9f2a4c8e-6b21-4d0f-a97b-5e8c1d2f6a3b \
  -H "Authorization: Bearer $SENDAI_API_KEY"
Response
200 OK
{ "status": "success", "message": "api token revoked" }

A malformed id returns 400 invalid token id. Note that revoking an id that does not exist does not return 404 — treat a 200 as "this key is now not valid" rather than as proof the key existed.

Rotating without downtime

Because a key is valid until revoked, you can overlap the old and the new and never drop a message:

  1. Create the replacement key.
  2. Deploy it to the service, alongside or in place of the old one.
  3. Confirm traffic has moved — new sends succeed with the new key.
  4. Revoke the old key.

Revoking before step 3 is what causes an outage. Keep the overlap short, but do keep it.

Handling keys safely

  • One key per service. Separate keys for your orders service, your marketing job, and your staging environment mean you can revoke one without touching the others.
  • Never commit a key. Keep them in environment variables or a secret manager, not in source control, client-side JavaScript, or a mobile app — anything shipped to a user's device can be read by that user.
  • Never log the Authorization header. Redact it in request logs and error reporters.
  • Rotate on a cadence, and immediately if a key is exposed.

Next steps