minimoth

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_..."
}

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 (10 digits starting with 6–9, with or without +91), and not a number in a supported international market either. See International WhatsApp OTP for supported markets.
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.

International markets

Code Status Description
REGION_NOT_ENABLED 403 The phone number’s market exists, but this project hasn’t turned it on yet. Enable it from the project’s International WhatsApp OTP card in the dashboard, which shows the rate before you turn it on. See International WhatsApp OTP.
INTERNATIONAL_WHATSAPP_FAILED 502 A real WhatsApp delivery attempt to an international number failed. There is no SMS fallback for these numbers. The message states whether the charge was refunded — it always is unless the refund itself failed (rare; contact support if it persists).
INTERNATIONAL_WHATSAPP_BLOCKED 502 This number has had too many recent WhatsApp delivery failures and is temporarily blocked — no delivery was attempted and no charge was made for this call. The block clears on its own once the window passes without a new real failure.

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.

Identity

Code Status Description
IDENTITY_DELETE_DISABLED 403 Identity deletion isn’t turned on for this project. Enable it from the project’s Identity settings card in the dashboard. See Identity.
IDENTITY_LOOKUP_DISABLED 403 Identity lookup isn’t turned on for this project. Enable it from the project’s Identity settings card in the dashboard. See Identity.
IDENTITY_NOT_FOUND 404 No identity with that id, or it belongs to a different project.

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: an empty or non-string phone number. Spaces and hyphens are stripped, not rejected — +1-2025551234 and +12025551234 both work. 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 response had no error code at all — an unparseable body, or a response shape that never included one. 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 →