Errors
Every error code the API can return, and what to do about each one.
A failed request returns the same RFC 7807
problem document, served as application/problem+json, whatever went wrong:
{
"type": "https://menaverify.com/docs/errors#rate_limited",
"title": "Too Many Requests",
"status": 429,
"detail": "Rate limit of 100 requests per second exceeded.",
"instance": "/v1/verify/phone",
"code": "rate_limited"
}code is stable and safe to branch on. detail is written to be shown to a
person. type links to the section below.
An invalid value is not an error
A value that fails its checks returns 200 with valid: false. See
Reading a result.
Codes
invalid_request
400 — The request itself is malformed: a missing value, a body that is not
valid JSON, a batch over 100 items, or a country code the API cannot parse.
Fix the call. Retrying unchanged will fail the same way.
unauthorized
401 — No credential, or one that is not recognised. The key may be
mistyped, revoked, or missing its Bearer prefix.
Check Authentication.
forbidden
403 — The credential is valid but not allowed here. Usually a session token
sent to /v1/verify, or an API key sent to a dashboard endpoint.
not_found
404 — No such route or resource — for example revoking a key id that does not exist, or asking for a country outside the registry.
rate_limited
429 — You went over the per-second ceiling for the key. The allowance is on
every successful response as X-RateLimit-Limit.
Back off and retry: wait, then retry with exponential backoff and jitter. See Usage and rate limits.
free_checks_exhausted
429 — Only from the playground: an anonymous visitor has used all 3 free checks. The allowance is counted per IP address and per browser fingerprint.
Create a free account to keep going. Signed-in checks are unlimited, and API keys are never subject to this limit.
unsupported_country
400 — The resolved country is not in the registry. The error carries
country (what was resolved) and supported (what would have worked).
Only the United Arab Emirates is supported today.
internal_error
500 — Something failed on our side.
Safe to retry with backoff. If it persists, the health of the service is on the status page.
Retrying
| Code | Retry | Why |
|---|---|---|
rate_limited | Yes, with backoff | The ceiling is per second |
internal_error | Yes, with backoff | Transient by definition |
free_checks_exhausted | After signing up | The playground allowance does not refill on retry |
invalid_request | No | Fix the request |
unauthorized / forbidden | No | Fix the credential |
not_found | No | Fix the route or id |
Verification is a pure check with no side effects, so a retried call is safe.