Errors
Every error has the same shape and a stable code you can switch on.
{
"code": "VALIDATION_FAILED",
"message": "Some fields need attention.",
"fields": [
{
"path": "to",
"message": "Enter a valid Ghana mobile number."
}
],
"traceId": "req_9f2k4m6n8p1q3r5t"
}code— stable and machine-readable. Messages may be reworded; codes won’t.message— a plain explanation you can log or show to an operator.- Extra fields where they help:
fields(validation),retryAfterSeconds(limits, also theRetry-Afterheader),attemptsRemaining(OTP),requiredScope. traceId— also theX-Request-Idheader. Quote it when contacting support.
Retrying
- 4xx: fix the request; don’t retry unchanged (except 429 after the wait).
- 429: wait
retryAfterSeconds. - 5xx and timeouts: retry with backoff, using the same
Idempotency-Keyso nothing is sent twice.
All codes
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
INVALID_API_KEY | 401 | The key is missing, wrong, expired or revoked. | Send `Authorization: Bearer nxk_…` with an active key. |
INSUFFICIENT_SCOPE | 403 | The key doesn't have the permission this endpoint needs. | Create a key with the scope named in `requiredScope`. |
PROJECT_NOT_ACTIVE | 403 | The key's project is disabled or archived. | Enable the project in the dashboard. |
PROJECT_NOT_IN_PRODUCTION | 403 | A production key was used while its project is in sandbox. | Use a sandbox key, or move the project to production. |
RATE_LIMITED | 429 | Too many requests for this key this minute. | Wait `retryAfterSeconds` (also in the Retry-After header). |
VALIDATION_FAILED | 400 | Some fields are missing or invalid. | See `fields` for each problem. |
INVALID_JSON | 400 | The body isn't valid JSON. | Send `Content-Type: application/json` with a JSON body. |
NOT_FOUND | 404 | No such endpoint. | Check the method and path. |
SMS_NOT_ENABLED | 409 | SMS is off for this project. | Turn SMS on in project settings. |
SENDER_NOT_APPROVED | 400 | Production messages need an approved sender ID. | Request one under SMS → Sender IDs. |
RECIPIENT_SUPPRESSED | 400 | The number opted out of your messages. | Don't message it, or remove it from your suppression list if they opted back in. |
INSUFFICIENT_FUNDS | 402 | Your wallet can't cover the price. Nothing was sent or charged. | Add funds, then retry. |
PRICING_NOT_CONFIGURED | 503 | No price is set for this destination yet. | Contact Nopexo support. |
SMS_RATE_LIMITED | 429 | Project or organization send limit reached. | Wait `retryAfterSeconds`, or use /v1/sms/bulk for large sends. |
TOO_MANY_RECIPIENTS | 400 | More recipients than a batch allows. | Split into batches of up to 10,000. |
MESSAGE_NOT_FOUND | 404 | No message with this ID in this project and environment. | Check the ID and that you use the same key environment. |
BATCH_NOT_FOUND | 404 | No batch with this ID in this project and environment. | Check the batch ID. |
OTP_NOT_ENABLED | 409 | OTP is off for this project. | Turn OTP verification on in project settings. |
OTP_SENDER_NOT_CONFIGURED | 409 | No sender ID is set for production codes. | Choose one in Verify → Settings, or pass `sender`. |
DESTINATION_NOT_ALLOWED | 422 | The number's network isn't allowed by your Verify settings. | Allow the network, or ask the user for another number. |
OTP_RATE_LIMITED | 429 | Too many codes from this project this minute (or the sandbox daily limit). | Wait `retryAfterSeconds`. |
OTP_PHONE_RATE_LIMITED | 429 | Too many codes sent to this number recently. | Ask the user to wait; show `retryAfterSeconds`. |
OTP_PHONE_BLOCKED | 429 | Too many wrong codes for this number; it's blocked for an hour. | Ask the user to try later. |
SPEND_LIMIT_REACHED | 403 | The project's daily OTP spending limit was reached. | Raise it in Verify → Settings. |
OTP_NOT_FOUND | 404 | No verification with this request ID for this project and environment. | Check the ID; start a new verification if needed. |
OTP_INCORRECT | 422 | Wrong code. One attempt used. | Let the user retry; `attemptsRemaining` says how many tries are left. |
OTP_EXPIRED | 410 | The code expired. | Start a new verification. |
OTP_ALREADY_VERIFIED | 409 | This verification already succeeded; codes are single use. | Treat the user as verified once; don't re-check. |
OTP_MAX_ATTEMPTS | 429 | Too many wrong codes for this verification. | Start a new verification. |
OTP_CANCELLED | 410 | This verification was cancelled. | Start a new verification. |
OTP_RESEND_COOLDOWN | 429 | A code was sent too recently. | Wait `retryAfterSeconds`. |
OTP_RESEND_LIMIT | 429 | No more resends for this verification. | Start a new verification. |
PAYLOAD_TOO_LARGE | 413 | The request body is too large. | Send fewer recipients per batch. |
INTERNAL_ERROR | 500 | Something failed on Nopexo's side. | Retry with the same Idempotency-Key; contact support with the traceId if it persists. |