API errors
HTTP statuses, error codes, and retry guidance.
Errors
The API uses conventional HTTP status codes to signal outcome, and a structured JSON body to describe the reason. Every error response has the same shape — code, short message, and optional detail with extra context.
{ "error": { "code": 400301, "message": "invalid uuid format", "detail": "see https://en.wikipedia.org/wiki/Universally_unique_identifier" }}
Fields:
| Field | Type | Description |
|---|
error.code | number | A fine-grained application-level code. Combines the HTTP status with a reason category — the full list is below. |
error.message | string | Short human-readable explanation, suitable for logs. |
error.detail | string | Optional. Additional context — a list of failing fields for validation errors, a link to external docs, or the specific value that was rejected. |
HTTP status code summary
| Code | Name | Description |
|---|
| 200 | OK | Request succeeded. The response body contains the requested object. |
| 201 | Created | Resource was created. The response body contains the new object. |
| 204 | No Content | Request succeeded; the endpoint has no body to return (typically after a DELETE). |
| 400 | Bad Request | The request is malformed — missing required fields, wrong types, or invalid parameter values. |
| 401 | Unauthorized | Authentication is missing, invalid, or expired. Check the Authorization header. |
| 402 | Payment Required | The workspace plan or balance does not cover this operation. |
| 403 | Forbidden | The token is authenticated but lacks permission for this resource or action. |
| 404 | Not Found | The resource does not exist, or it exists but is not visible to this token. |
| 429 | Too Many Requests | Rate limit exceeded. Respect the Retry-After response header before retrying. |
| 5xx | Server Error | Unexpected server error. Safe to retry with exponential backoff; contact support if it persists. |
Numeric codes returned in error.code. The first three digits of each code always match the HTTP status of the response.
Authentication & access codes (1xxxxx)
| Code | Name | Description |
|---|
| 1 | IO_ERROR | The request body could not be read — usually an empty or malformed payload, or a dropped connection mid-upload. |
| 100101 | AUTH_AUTHORIZATION_HEADER_NOT_FOUND | The Authorization header is missing from the request. |
| 100102 | UNAUTHORIZED | The token is missing, invalid, or expired. |
| 100103 | ACCESS_DENIED | The token is valid but does not grant access to this resource or scope. |
| 100104 | INVALID_USERNAME_OR_PASSWORD | The credentials provided to the sign-in endpoint do not match any account. |
| 100105 | INVALID_CONFIRMATION_TOKEN | The email-confirmation token is unknown or expired. Request a new one. |
| 100106 | LIMIT_REACHED | A per-workspace quota or rate limit has been hit. |
| 100107 | USER_IS_NOT_OWNER | The action requires workspace-owner privileges; the current user is not the owner. |
Bad request & validation codes (4xxxxx)
| Code | Name | Description |
|---|
| 400101 | JSON_SYNTAX_ERROR | The request body is not valid JSON. |
| 400102 | JSON_UNMARSHAL_TYPE_ERROR | A field in the body has a type that the API did not expect (e.g. a string where a number is required). |
| 400201 | HAS_ALREADY_BEEN_TAKEN | A uniqueness constraint was violated — a value with the given key already exists. |
| 400202 | EMAIL_IS_ALREADY_TAKEN | An account with this email address already exists. |
| 400203 | NAME_IS_ALREADY_TAKEN | An entity with this name already exists in the current scope (workspace, project, folder). |
| 400204 | INVITATION_IS_ALREADY_EXIST | An invitation has already been sent to this recipient. |
| 400205 | INVITATION_IS_ALREADY_APPROVED | The invitation has already been accepted — it cannot be accepted again. |
| 400206 | BILLING_ACCOUNT_IS_ALREADY_EXIST | A billing account is already attached to this workspace. |
| 400207 | NOT_ENOUGH_MONEY | The workspace balance is insufficient for this operation. |
| 400208 | NO_BILLING_ACCOUNT | The workspace has no billing account yet. Create one before using paid features. |
| 400209 | NO_PAYMENT_METHOD | No payment method is configured on the billing account. |
| 400210 | NOT_ENOUGH_REQUIRED_PRODUCTS | The current plan is missing one or more products this operation depends on. |
| 400211 | NOT_ALLOWED_ADDITIONAL_FOR_TRIAL | Add-ons cannot be purchased while the workspace is on a trial plan. |
| 400212 | SUBSCRIPTION_NOT_PAID | The workspace has unpaid invoices. Clear them before continuing. |
| 400213 | EMAIL_NOT_CONFIRMED | The user's email address has not been confirmed yet. |
| 400214 | EMAIL_NOT_FOUND | No account is associated with the given email. |
| 400215 | RESET_TOKEN_NOT_FOUND_OR_EXPIRED | The password-reset token is unknown or expired. Start the reset flow again. |
| 400216 | NOT_ALLOWED_ORDER_FIELD | The order parameter refers to a field that this endpoint cannot sort by. |
| 400301 | — | One of the UUID parameters in the URL, query, or body has an invalid format. |
| 400400 | UNEXPECTED_VALUE | A parameter value is outside the set of allowed values (usually an enum). |
Other error codes (402 / 404 / 500)
| Code | Name | Description |
|---|
| 402402 | VALIDATION_ERROR | One or more fields failed validation. The detail field typically lists the failing fields and the reasons. |
| 404404 | NO_SUCH_ENTITY | The referenced object does not exist, has been deleted, or is not visible to this token. |
| 500500 | INTERNAL_SERVER_ERROR | An unexpected error occurred on the server. Safe to retry with exponential backoff. |
Handling errors
- Retries.
5xx responses and network timeouts are safe to retry. Use exponential backoff and cap the number of attempts. 4xx responses other than 429 should not be retried — fix the request. - Rate limits. On
429, pause for the number of seconds in the Retry-After header before retrying. Do not retry immediately. - Validation. For
402402 VALIDATION_ERROR, expect error.detail to contain the field-level breakdown. Surface those messages to the user so they can correct the input. - Logging. Log
error.code rather than error.message for alerting and analytics — codes are stable, messages are not.