Errors
Every error from /v1 has the same small JSON shape and a fixed HTTP status per code.
The error shape
Every non-2xx answer from /v1 is a JSON object with a short English error message (for logs and support, never for display), a machine-readable code, and, for validation errors, fields. Messages never contain names, addresses or clinical text.
{
"error": "invalid body",
"code": "INVALID",
"fields": { "email": "invalid" }
}This is Elavinya's own envelope, not RFC 9457 problem details. Branch on code, not on error.
Codes
| Code | Status | Meaning |
|---|---|---|
| INVALID | 400 | The request body, query or path did not pass validation. fields names each field and why. |
| UNAUTHENTICATED | 401 | No valid session. Sign in again. |
| EMAIL_NOT_VERIFIED | 403 | The account has not proved its email address yet. |
| STEP_UP_REQUIRED | 403 | A sensitive action: prove it is you again and send the proof in x-step-up. |
| FORBIDDEN | 403 | Signed in, but your role does not allow this on this record. |
| WRONG_REGION | 403 | The x-region header names a different region from the one that answered. |
| NOT_FOUND | 404 | No such route, or no such record that you may see. |
| CONFLICT | 409 | The record changed since you read it, or the action clashes with its current state. |
| GONE | 410 | The record or link existed but has ended (for example, an expired secure link). |
| RATE_LIMITED | 429 | Too many requests. Wait, then try again (see Rate limits). |
| UNAVAILABLE | 503 | A service this request depends on is not available. Try again later. |
| INTERNAL | 500 | Our error. It has been logged without personal data; try again later. |
Errors from /api/auth
Sign-in requests answer in the shape of the auth library: { "code": "...", "message": "..." }. Codes you may meet:
| Code | Status | Meaning |
|---|---|---|
| SIGN_IN_RATE_LIMITED | 429 | Too many password attempts. The answer offers an emailed sign-in link instead (fallback: "magic-link"). |
| TURNSTILE_FAILED | 403 | The security check token was missing, invalid, used before, or solved for another site or action. |
| TURNSTILE_UNAVAILABLE | 503 | The security check could not run. Nothing was created or sent. |
| EMAIL_NOT_VERIFIED | 403 | The account has not proved its email address yet. |
| STEP_UP_REQUIRED | 403 | Adding a way to sign in needs a recent sign-in or a step-up proof. |