Errors & rate limits
Errors are JSON with a stable machine code and a human explanation:
{ "error": "BAD_CHECK_DIGIT", "detail": "not a valid ADAS code" }
Error codes
| HTTP | error | Meaning |
|---|---|---|
| 400 | EMPTY / BAD_CHARSET / BAD_STRUCTURE / BAD_LENGTH | input is not a well-formed code |
| 400 | BAD_CHECK_DIGIT | well-formed but a digit is wrong — re-ask the human, don't retry |
| 400 | BAD_PHONE | phone not E.164 |
| 401 | BAD_CREDENTIALS | wrong phone/password, or invalid/revoked key |
| 404 | NOT_FOUND | valid code, but nothing registered under it |
| 409 | PHONE_TAKEN | account already exists — log in instead |
| 422 | OUTSIDE_COVERAGE | coordinate is not inside any active country's zones |
| 503 | OTP_DISABLED | phone verification not yet available |
The distinction between BAD_CHECK_DIGIT (400) and NOT_FOUND (404)
matters operationally: a 400 means the code was miscommunicated — prompt the
user to re-read it; a 404 means the code was never issued or was
deactivated.
Rate limits
| Scope | Default |
|---|---|
| Address resolution | 120/min per client |
| Auth endpoints | 15/min per IP |
| OTP requests | 10/hour per IP |
Throttled requests return 429 with a Retry-After header. Higher limits
come with partner agreements — hello@adas.africa.