Idempotency keys
Retry safely. The same key never sends twice.
Developers
Send messages and verification codes with one HTTPS request. JSON in, JSON out, clear errors and signed webhooks.

Create an API key in your dashboard, then make one request. The response comes back right away with an ID you can track.
https://app.traitzsms.com/api/v1
{
"id": "5b0f6d9e-8a3c-4c2a-9f6e-1d2c3b4a5e6f",
"to": "+237699000001",
"status": "queued",
"segments": 1,
"cost_credits": 1,
"client_reference": "order-4821",
"created_at": "2026-10-29T14:00:00Z"
}curl https://app.traitzsms.com/api/v1/messages \
-H "Authorization: Bearer tsms_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-4821-1" \
-d '{"to":"+237699000001","from":"MYSHOP","message":"Your order #4821 is on its way.","client_reference":"order-4821"}'| POST | /messages | Send one SMS |
| POST | /messages/bulk | Send to up to 1,000 numbers |
| GET | /messages | List and filter your messages |
| GET | /messages/{id} | Status, parts, cost and errors of one message |
| GET | /sender-ids | Your sender IDs and their status |
| GET | /balance | Credits left |
Retry safely. The same key never sends twice.
OTP messages use their own queue, ahead of bulk campaigns.
Attach your own order or user ID and find any message by it.
Generate a client in your language from our OpenAPI 3.1 file.
We call your URL when a message is submitted, delivered or fails. Each call is signed with your endpoint secret and carries a timestamp, so you can reject fakes and replays. Failed calls are retried for 24 hours.
import crypto from 'node:crypto'
// rawBody: the exact bytes we sent, before JSON parsing.
function isFromTraitzSms(rawBody, headers, secret) {
const timestamp = Number(headers['x-traitzsms-timestamp'])
if (Math.abs(Date.now() / 1000 - timestamp) > 300) return false // replay
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex')
const received = headers['x-traitzsms-signature'] || ''
return expected.length === received.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(received))
}| HTTP | error | |
|---|---|---|
| 400 | validation_failed | A field is missing or invalid |
| 401 | unauthorized | The API key is missing, invalid or revoked |
| 402 | insufficient_credits | Not enough credits for this request |
| 403 | sender_not_allowed | This sender ID is not approved for you |
| 409 | duplicate_request | Same idempotency key, different body |
| 422 | invalid_recipient | Not a valid Cameroon mobile number |
| 429 | rate_limited | Limit reached, see the Retry-After header |
| 503 | service_unavailable | Temporary problem, safe to retry |
Ready when you are
Create your account, top up with mobile money and send in minutes.