Getting started
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.
What sandbox mode is
Sandbox is a property of the API key. A request made with a sk_test_ key goes to the same endpoints as a live one and is validated the same way, then the message is recorded as sent without reaching a network and without touching the wallet.
What sandbox checks, and what it skips
| Check | Sandbox | Production |
|---|---|---|
| API key active and scoped for the endpoint | Yes | Yes |
| Route present (transactional or promotional) | Yes | Yes |
| Message present, within length, passes the content policy | Yes | Yes |
| At least one valid Nigerian number; invalid and repeated numbers removed | Yes | Yes |
| Opted-out numbers removed | Yes | Yes |
| Transactional: one recipient and an Idempotency-Key | Yes | Yes |
| Transactional: the workspace's limits per minute and per day | No | Yes |
| Platform maintenance mode | Yes | Yes |
| Workspace active, KYC approved, production access | No | Yes |
| Sender ID approved for the route | No | Yes |
| Wallet not frozen and balance covers the cost | No | Yes |
| Promotional hours (08:30 to 19:30 WAT) | No | Yes |
| Sent to a network | No | Yes |
| Wallet reserved and charged | No | Yes |
What a sandbox send returns
- The send response is the same shape as a live one, with
"mode": "sandbox".estimated_cost_koboshows what the send would cost live;reserved_cost_kobois 0. - Each message moves from
queuedtoacceptedand stays there. There is no delivery report in sandbox, so no message becomes delivered, failed or expired. customer_price_koboon a sandbox message is 0.- Sandbox messages appear in
GET /v1/messagesalongside live ones, told apart bymode. - Webhooks fire for sandbox sends:
message.sentwhen each message is recorded, andbatch.completedwhen the batch finishes.message.deliverednever fires in sandbox; use the endpoint test to exercise your receiver.
Using it
# Development
export SENDOZI_API_KEY="sk_test_..."
# Production
export SENDOZI_API_KEY="sk_live_..."curl -X POST https://api.sendozi.com/v1/sms/send \
-H "Authorization: Bearer $SENDOZI_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: sandbox-check-001" \
-d '{
"sender": "YourBrand",
"recipient": "08012345678",
"message": "Sandbox test.",
"route": "promotional"
}'What to test in sandbox
- Recipient handling: send a mix of formats (08012345678, 8012345678, +2348012345678), a duplicate and an invalid number, and check
accepted_count,duplicates_removedandinvalid_count. - Page counting: send your longest rendered message and check
estimated_cost_kobomatches your estimate. One character outside GSM-7 halves the characters per page. - Error handling: branch on
error.code, never on the message text. - Idempotency: send twice with the same key and body, and confirm the second answer has the same
batch_id. - Webhook receivers:
POST /v1/webhooks/endpoints/{id}/testsends a signedtest.pingso you can check signature verification.
Before you switch keys
- 1
Sender ID approved for the route you send on
Otherwise sender_id_not_approved, or sender_id_route_mismatch for a transactional send on a Sender ID approved for promotional only.
- 2
Wallet funded for the whole send
The full estimated cost is reserved when a live send is accepted.
- 3
Webhook endpoint registered and tested
Before real deliveries depend on it.
- 4
One live message to your own phone
The only test of the last mile.
Frequently asked questions
- Is there a separate sandbox URL?
- No. Sandbox uses the same base URL and endpoints. The sk_test_ key prefix selects it.
- Does sandbox cost anything?
- No. The estimated cost is reported in the response, but nothing is reserved or charged.
- Will a sandbox message reach a real phone?
- No. A sandbox message is never handed to a network.
- Why did my send pass in sandbox and fail live?
- Sandbox skips the account checks. The usual causes are a Sender ID not approved for the route, or an unfunded wallet.
Related reading
Getting started
Quickstart: send your first SMS
Create a sandbox key, send your first SMS, read the queued batch it returns, follow the message to delivery, and switch to production. A complete first integration.
Getting started
Authentication, API keys and scopes
How to authenticate Sendozi API requests, sandbox and production keys, the scopes that limit what a key can do, and how to rotate or revoke a key without surprises.
Reliability
Errors and the response envelope
The Sendozi response envelope, every error code the API returns with its HTTP status and fix, which errors are safe to retry, Retry-After, and how request_id traces a request.
Reliability
Idempotency and safe retries
How the Idempotency-Key header works on Sendozi send endpoints, what a repeat returns, why the body must be byte-for-byte identical, how long keys last, and how to choose one.