Errors always use the same envelope, so you can switch on error.code rather than parsing messages.
{
"success": false,
"error": { "code": "QUOTA_EXCEEDED", "message": "Daily OTP quota exceeded." }
}
| Code | HTTP | Meaning | What to do |
|---|---|---|---|
| INVALID_API_KEY | 401 | Key missing, malformed or unknown. | Check the key stored in your server config. |
| API_KEY_DISABLED | 403 | Key revoked or disabled. | Generate a new key in the dashboard. |
| ACCOUNT_SUSPENDED | 403 | The linked account is not active. | Contact support. |
| METHOD_NOT_ALLOWED | 405 | Non-POST request. | Use POST with a JSON body. |
| VALIDATION_ERROR | 422 | A field is missing or invalid. | Fix the payload; the message names the field. |
| RESEND_COOLDOWN | 429 | A code was just sent to this destination. | Wait for the seconds in the message / Retry-After. |
| QUOTA_EXCEEDED | 429 | Daily or monthly quota reached. | Upgrade the plan or wait for the reset. |
| RATE_LIMIT_EXCEEDED | 429 | Per-IP or per-key request limit hit. | Back off using the Retry-After header. |
| REQUEST_NOT_FOUND | 404 | Unknown request_id for this account. | Send a new OTP and reuse the fresh ID. |
| OTP_EXPIRED | 410 | The code expired. | Send a new code. |
| ALREADY_VERIFIED | 409 | The request was verified earlier. | Treat the user as verified. |
| INVALID_OTP | 401 | Wrong code. | Let the user retry until attempts run out. |
| MAX_ATTEMPTS_REACHED | 429 | Attempt limit for this request exhausted. | Issue a new OTP request. |
| DELIVERY_FAILED | 502 | No channel accepted the message. | Verify SMTP / SMS provider settings. |
| MAINTENANCE | 503 | The service is in maintenance mode. | Retry shortly. |
| SERVER_ERROR | 500 | Unexpected failure. | Retry once, then contact support with the request ID. |