Errors
Branch on statusMessage and HTTP statusCode, not on translated error.message.
Envelope
json
{
"success": false,
"statusCode": 400,
"statusMessage": "VALIDATION_ERROR",
"results": null,
"error": {
"message": "Validation error",
"data": []
}
}Status messages
statusMessage | HTTP | When |
|---|---|---|
SUCCESS | 200 | Generic OK |
CREATED | 200 | Resource created |
UPDATED | 200 | Mutation applied (fulfillment actions) |
DELETED | 200 | Deleted |
DATA_LOADED | 200 | List / read |
VALIDATION_ERROR | 400 | Schema or business rule (including maintenance mode) |
SLUG_TAKEN | 400 | Unique slug clash |
OUT_OF_STOCK | 400 | Cart / place |
CART_EMPTY | 400 | Place or cart action |
INVALID_CREDENTIALS | 401 | Bad staff password or OTP |
INVALID_TOKEN | 401 | Bad token |
TOKEN_EXPIRED | 401 | Expired OTP / token |
AUTHENTICATION_REQUIRED | 401 | Missing customer or staff JWT |
UNAUTHENTICATED | 401 | JWT rejected |
FORBIDDEN | 403 | Authenticated but not allowed |
ACCESS_DENIED | 403 | Missing permission (e.g. orders:update) |
RESOURCE_NOT_FOUND | 404 | Unknown id |
RESOURCE_EXISTS | 409 | Duplicate |
RATE_LIMITED | 429 | Redis rate limit |
TOO_MANY_ATTEMPTS | 429 | OTP / login throttle |
INTERNAL_ERROR | 500 | Unexpected |
SERVICE_UNAVAILABLE | 503 | Dependency down |
Auth failures
| Situation | Typical code |
|---|---|
| Customer route without Bearer | AUTHENTICATION_REQUIRED / UNAUTHENTICATED |
| Staff route without Bearer | Same |
Picker/driver POST without orders:update | ACCESS_DENIED |
| Wrong role UI | Still 200 on /auth/me — hide screens using roleKey |
Store closed
Mutations to /v1/cart, /v1/orders (POST), and /v1/account/wishlist while maintenance mode is on return VALIDATION_ERROR with a localized store-closed message.
Client checklist
- If
success === false, showerror.messageto the user. - If
statusCode === 401on a customer app, callPOST /v1/auth/refreshonce and retry. If refresh fails, send the user to OTP. - If
statusCode === 401on picker/driver, refresh the staff JWT once; if that fails, send the user to staff login. - Retry 429 with backoff.
- After every fulfillment POST, reload the order; do not assume local state.
- Assistant
POST /v1/assistant/messagesandGET /v1/notifications/sseare SSE — parseevent:/data:lines, not the JSON envelope.