API errors
Every failure returns the same four fields. Branch on error
— it is a stable string, and it will not be renamed under an integration
that was correct when it was written. retryable is a
boolean: true means the identical request may succeed
later, false means change something first.
{
"error": "insufficient_credit",
"message": "Not enough credit to accept this request…",
"docs_url": "/docs/errors#insufficient_credit",
"retryable": false
}
26 codes. The HTTP status is worth reading alongside the code: a 4xx is about your request, a 5xx is about us.
Credentials
The key itself — missing, wrong, retired, or not allowed to do this.
No API key was supplied. Send it as `Authorization: Bearer <key>` or `X-Api-Key: <key>`.
That API key is not valid.
That API key has been revoked. Issue a new one from your dashboard.
That API key has expired. Issue a new one from your dashboard.
This API key does not carry the scope required for this endpoint.
This API key is restricted to an IP allowlist that does not include this address.
This account is suspended. Contact support to restore service.
Throttling
You are going faster than the account is allowed to.
You are sending faster than your plan allows. Slow down or upgrade for a higher rate.
Money
Refused before anything was charged.
Not enough credit to accept this request. Top up and send it again — nothing was charged.
The recipient
Refused at the boundary and never charged. On a multi-recipient send these appear per recipient inside a 200 instead.
That is not a phone number.
This gateway carries Bhutanese numbers only (+975), on a prefix an operator claims.
The message
The text or its options ask for more than the plan carries. Nothing is ever truncated to fit.
This message needs more segments than your plan permits. Shorten it or upgrade — it was not truncated and not charged.
This message needs UCS-2 (it contains a character outside the GSM alphabet), which your plan does not include.
More recipients than your plan permits in one request. Split it into smaller batches.
Scheduled sending is not included in your plan.
Priority sending is not included in your plan. It moves a message ahead of ordinary traffic and is charged at a higher per-segment rate.
The sender ID
Who the message appears to come from.
That sender ID is not a valid format.
That sender ID is reserved and cannot be registered.
Your plan sends under the platform sender ID and cannot set its own.
That sender ID is not approved for your account.
The request itself
The request was understood and still could not be carried out.
No such resource.
This message has left the queue and can no longer be cancelled.
The request body is missing a required field or has one of the wrong type.
That HTTP method is not supported on this endpoint.
Ours, not yours
Nothing you can fix, and nothing you were charged for.
Something went wrong on our side. Nothing was charged.
Other
Newly added codes that have not been filed into a family yet.
The platform is in a maintenance window and is not accepting messages right now.
Only rate_limited and internal_error are worth
repeating. Every other code refuses the request as written, so an
identical retry gets an identical refusal — and a loop of them is how a
clear answer turns into a throttle. There is no Retry-After
header on this API; your plan's ceiling is on
/api/v1/pricing as max_tps,
and the limit is per second, so a short pause clears it.
WONS SMS