Errors
Errors are returned as JSON with a stable machine-readable code and a human-readable message. Handle the code, log the message.
error shape
{
"error": {
"code": "insufficient_balance",
"message": "Wallet balance is too low to reserve funds for this message."
}
}| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| unauthorized | 401 | API key missing, malformed or revoked. | Send Authorization: Bearer lap_..., create a new key if revoked. |
| invalid_to | 400 | Destination is not a valid E.164 number. | Use international format, e.g. +27821234567. |
| unsupported_destination | 400 | Destination country is not enabled for your account. | Currently South Africa (+27) only. Contact us for other routes. |
| body_required | 400 | Message body is empty. | Send a non-empty body. |
| body_too_long | 400 | Body exceeds the maximum segment count. | Shorten the message - check the segments field in responses. |
| insufficient_balance | 402 | Wallet can't cover the estimated charge. | Top up your wallet, or use a test key for development. |
| production_not_approved | 403 | Live sending isn't enabled for this organization yet. | Complete onboarding from the dashboard. |
| sending_paused | 403 | A kill switch is active for your key, org, or the platform. | Check the dashboard banner or contact support. |
| suppressed_destination | 403 | The number opted out, or is blocked platform-wide. | Stop sending to it. Remove it from your list - re-sending is a legal risk, not just an error. |
| idempotency_conflict | 409 | Same Idempotency-Key reused with a different request body. | Use a fresh key per logical send; reuse only for retries of the same send. |
| rate_limited | 429 | Too many requests for this key. | Back off and retry with jitter after one second. |
| spend_limit_exceeded | 429 | An hourly, daily or monthly spend limit on your account or this key would be exceeded. | Raise the limit on the wallet page, or wait for the window to reset. Nothing was charged. |
| destination_velocity_exceeded | 429 | Too many messages to the same number within an hour - usually a retry loop. | Check your send logic for duplicates. Contact support if you have a legitimate need for a higher limit. |
Retries: 429 and 5xx responses are safe to retry with the same Idempotency-Key header - you will never be double-charged for the same logical message.