Every failure returns one of these codes. They are stable strings: branch on them.
Only five codes are retryable
Out of the whole catalogue, exactly five mean "try again and it might work":
| Code | HTTP | Why it can succeed on a retry |
|---|
RATE_LIMITED | 429 | You are going too fast. Back off and retry. |
PIN_RATE_LIMITED | 429 | Too many PIN requests for this number. Wait before retrying. |
INTERNAL_ERROR | 500 | Something failed on our side. Retry with backoff. |
FRAUD_CHECK_UNAVAILABLE | 503 | The anti-fraud check could not be completed. Nothing was consumed: retry. |
ANTIFRAUD_SCRIPT_UNAVAILABLE | 503 | We could not fetch the protection script. Retry before serving the page. |
Everything else below is retryable: false. Retrying it will fail identically.
Authentication and access
| Code | HTTP | What it means |
|---|
UNAUTHENTICATED | 401 | No token, or not a valid one. |
CREDENTIAL_REVOKED | 401 | The token existed and has been withdrawn. Contact the operator team. |
IP_NOT_ALLOWLISTED | 403 | Your source address is not registered. The response tells you the address we saw: compare it with what you registered. |
ABILITY_NOT_GRANTED | 403 | Your credential is valid but not permitted for this operation. |
SERVICE_NOT_FOUND | 404 | No such service, none you have access to, or one that has been removed from the catalogue. The three are deliberately indistinguishable. |
SERVICE_NOT_ON_SHORT_CODE | 422 | The service is not on the short code your credential is bound to. |
SERVICE_NOT_ACTIVE | 409 | The service exists but is not live. |
Request problems
| Code | HTTP | What it means |
|---|
VALIDATION_FAILED | 422 | A field is missing or malformed. Also refused here: a serviceId that is not a number, which is checked before your grant is looked up. |
INVALID_MSISDN | 422 | The number is not a valid subscriber number. |
DUPLICATE_TRANSACTION_ID | 409 | This spTransactionId has been used for a different request. Generate a new one per attempt. |
PIN and OTP
| Code | HTTP | What it means |
|---|
PIN_NOT_REQUESTED | 422 | You are verifying a code that was never issued for this number and service. |
PIN_INVALID | 422 | Wrong code. |
PIN_EXPIRED | 422 | The code was correct once but has timed out. Issue a new one. |
PIN_ATTEMPTS_EXCEEDED | 422 | Too many wrong attempts. Issue a new code. |
Subscriber state
| Code | HTTP | What it means |
|---|
ALREADY_SUBSCRIBED | 409 | Already has a live subscription to this service. |
NOT_SUBSCRIBED | 409 | The operation needs a live subscription and there is none. |
SUBSCRIBER_BLACKLISTED | 403 | This number may not be subscribed or messaged. Do not retry on any channel. |
Limits
| Code | HTTP | What it means |
|---|
CONTENT_LIMIT_EXCEEDED | 429 | The subscriber's daily content budget for this service is spent. |
PURCHASE_DAILY_LIMIT_REACHED | 429 | The subscriber's purchase count limit for today is reached. |
PURCHASE_AMOUNT_LIMIT_REACHED | 429 | The subscriber's purchase value limit is reached. |
SHORT_CODE_PART_LIMIT_REACHED | 429 | The short code's own send budget is spent. |
These are ceilings on the subscriber or the short code, not on you: they reset, and the reset
is not something your retry can hurry.
Content and messaging
| Code | HTTP | What it means |
|---|
CONTENT_TOO_LONG | 422 | Longer than this service permits. Messages are not split: see Send SMS. |
CONTENT_NOT_ALLOWED_TODAY | 403 | This service does not deliver content on this day of the week. |
Charging
| Code | HTTP | What it means |
|---|
CHARGE_FAILED | 402 | The operator refused the charge. |
INSUFFICIENT_BALANCE | 402 | The subscriber cannot pay right now. |
PARENT_SUBSCRIPTION_REQUIRED | 409 | This purchase needs an active subscription to its parent service. |
PURCHASE_CHANNEL_NOT_ENABLED | 403 | One-time purchase is not enabled for this service. |
Anti-fraud
| Code | HTTP | What it means |
|---|
FRAUD_BLOCKED | 403 | The check ran and returned a negative verdict. Do not retry. |
FRAUD_CHECK_UNAVAILABLE | 503 | The check could not run. Retryable, and nothing was consumed. |
FRAUD_TRANSACTION_UNKNOWN | 422 | We have no record of this transaction identifier. Your page did not fetch the anti-fraud script with this ti, or used a different one. This is not a decline: it exists as its own code so that it cannot be mistaken for one. See Anti-fraud. |
ANTIFRAUD_SCRIPT_UNAVAILABLE | 503 | We could not fetch the script for your page. Retryable. |
Server
| Code | HTTP | What it means |
|---|
INTERNAL_ERROR | 500 | Our fault. Retry with backoff, and quote the requestId if it persists. |