Errors
Every error uses the same envelope and a small, predictable set of types.
The error envelope
details is present only when there is field-level information to report.
Always log meta.request_id — quoting it lets support trace the exact request.
Example error
{
"error": {
"type": "invalid_request",
"message": "Missing required field(s): pickup_address.",
"details": [
{ "field": "pickup_address", "issue": "required" }
]
},
"meta": { "request_id": "req_1a2b3c4d5e6f7a8b" }
}
Error types
| Type | HTTP | Meaning |
|---|---|---|
unauthorized | 401 | Missing, invalid or expired token. |
invalid_credentials | 401 | Login failed — incorrect email or password. |
forbidden | 403 | Authenticated, but not allowed to perform this action (e.g. a business you can't access, or a user-token-only endpoint called with an API key). |
email_unverified | 403 | Login blocked until the email address is verified. |
account_suspended | 403 | The acting business is suspended. |
usage_limit_reached | 403 | The current subscription plan's limit for this resource is reached (e.g. cars or drivers). |
not_found | 404 | The resource doesn't exist, or doesn't belong to your business. |
email_exists | 409 | An account or customer with that email already exists. |
confirmation_required | 409 | A destructive action needs confirmation — retry with force: true. |
feature_unavailable | 403 | The action needs a feature not enabled on the current plan or server. |
invalid_request | 400 / 422 | Malformed JSON (400) or failed validation (422). |
business_required | 422 | A user token with several accessible businesses needs the X-Business-Id header. |
rate_limited | 429 | Too many requests — see Rate limits. |
server_error | 500 | Something went wrong on our side. Safe to retry. |
HTTP status codes
| Code | When |
|---|---|
200 OK | Successful read or update. |
201 Created | A resource was created. |
204 No Content | Successful pre-flight (OPTIONS) response. |
401 / 403 / 404 | Auth, permission or existence problems. |
422 Unprocessable | The request was understood but failed validation. |
429 Too Many Requests | Rate limit exceeded. |
500 | Something went wrong on our side. Safe to retry. |
Never parse messages. Branch on
error.type and the HTTP
status, not on the human-readable message, which may change.