Error Codes
Every error response from the MiniMoth API has a stable code field you can use in your code to handle specific cases. Codes will not change — you can safely switch on them.
{
"error": "Human-readable message",
"code": "STABLE_CODE",
"request_id": "req_..."
}
"error": "Human-readable message",
"code": "STABLE_CODE",
"request_id": "req_..."
}
Authentication
| Code | Status | Description |
|---|---|---|
| MISSING_API_KEY | 401 | No X-Api-Key header was sent. |
| INVALID_API_KEY | 401 | The API key is not recognised. Check the key in your project settings. |
Validation
| Code | Status | Description |
|---|---|---|
| INVALID_PHONE | 422 | Phone number is not a valid Indian mobile number. Must be 10 digits starting with 6–9, with or without +91. |
| INVALID_OTP_CODE | 422 | The code field must be exactly 6 digits. |
| MISSING_ACCESS_TOKEN | 422 | The request body is missing the access_token field. |
| MISSING_REFRESH_TOKEN | 422 | The request body is missing the refresh_token field. |
OTP
| Code | Status | Description |
|---|---|---|
| OTP_RATE_LIMITED | 429 | Too many OTPs requested for this number. Limit is 3 per phone per 10 minutes. |
| OTP_NOT_FOUND | 400 | No active OTP exists for this phone number. It may have expired (10 min TTL) or already been used. |
| INVALID_OTP | 400 | The OTP code is incorrect. |
| VERIFY_RATE_LIMITED | 429 | Too many incorrect attempts for this OTP. The OTP is now locked — request a new one. |
| SMS_FAILED | 500 | Both WhatsApp and SMS fallback delivery failed. The charge was not applied. Retry after a moment. |
| OTP_REQUEST_NOT_FOUND | 404 | No OTP request found with that ID, or it does not belong to this project. Returned by GET /v1/otp/status/:otp_id. |
Billing
| Code | Status | Description |
|---|---|---|
| INSUFFICIENT_BALANCE | 402 | Wallet balance is too low to send an OTP. Top up from the dashboard. No OTP was sent and no charge was applied. |
Session
| Code | Status | Description |
|---|---|---|
| SESSION_EXPIRED | 401 | The refresh token has expired or is invalid. The user must re-authenticate. |
| INVALID_ACCESS_TOKEN | 401 | The access token is invalid or expired. Returned by session/logout when called with an expired token — refresh the session first, then retry the logout. |
| RATE_LIMITED | 429 | General rate limit exceeded — 1000 requests per minute per API key. Back off and retry. |
Node.js SDK
@minimoth/sdk-node surfaces every code above as-is via err.code — plus a few additional codes on top of the API's, for conditions the SDK catches locally before or instead of a network call.
| Code | Status | Description |
|---|---|---|
| INVALID_PHONE | — | SDK-only trigger, thrown client-side before any request is sent: spaces or hyphens in the phone number, or an empty string. Distinct from the API's own INVALID_PHONE (422) above, which fires server-side on a malformed but well-formatted number. |
| NETWORK_ERROR | — | The underlying fetch() call threw — the network was unreachable or the request otherwise never completed. |
| UNKNOWN_ERROR | — | The API returned an error code the SDK doesn't recognise — the SDK version may be older than the API. Check err.statusCode for the raw HTTP status. |
Try the full OTP flow interactively in the sandbox — no SMS sent, no credits consumed. The same Playground also has a live test to send a real OTP to your phone (uses your credits).
Test in Playground →