Errors
Error response format and the catalog of error codes in the OfficeGest API v2
Every error response in the API v2 has the same shape: an HTTP status code, and a JSON body with a stable code you can rely on in your integration.
Error body
{
"data": {
"code": "NOT_FOUND",
"message": "Article not found"
},
"meta": {
"trace_id": "9f86d081884c7d659a2feaa0c55ad01568f3a1c2b4d5e"
}
}| Field | Always present | Description |
|---|---|---|
data.code | Yes | Stable error code from the catalog below. Use it in your code instead of the message. |
data.message | Yes | Human-readable description. The text may change; do not parse it. |
data.errors | No | Details of the failure. On VALIDATION_FAILED it lists the invalid fields; some endpoints also use it on other codes, such as CONFLICT. |
meta.trace_id | Yes | Identifier of the request. |
Some errors carry extra fields in data or meta with more context. Ignore the fields you do not use.
Error codes
data.code | HTTP status | When it happens |
|---|---|---|
BAD_REQUEST | 400 | The request cannot be processed as sent. |
UNAUTHENTICATED | 401 | The token is missing, invalid or expired. |
INVALID_CREDENTIALS | 401 | The login credentials are wrong (POST /api/v2/auth/login). |
TOKEN_EXPIRED | 401 | The token has expired. Log in again to get a new one. |
FORBIDDEN | 403 | The token is valid but has no permission for this action, or the company does not have the module. |
NOT_FOUND | 404 | The resource or the endpoint does not exist. |
ARTICLE_NOT_FOUND | 404 | The article does not exist. Returned by the article endpoints instead of NOT_FOUND. |
CONFLICT | 409 | The request conflicts with the current state of the resource, for example a duplicate. |
ARTICLE_NOT_ACTIVE | 409 | The article is not active. |
ARTICLE_HAS_TRANSACTIONS | 409 | The article cannot be deleted because it has stock movements (DELETE /api/v2/stocks/articles/{article}). |
ARTICLE_HAS_DOCUMENTS | 409 | The article cannot be deleted because it is used in documents (DELETE /api/v2/stocks/articles/{article}). |
VALIDATION_FAILED | 422 | One or more fields are invalid. See data.errors. |
INVALID_FILTER | 422 | A filter[field][operator] parameter is invalid: the field cannot be filtered on that endpoint, the operator is not supported, or the value is not accepted. See data.errors. |
INVALID_CURSOR | 422 | The cursor parameter is invalid, or it does not match the requested sort. Start again from the first page. |
RATE_LIMITED | 429 | Too many requests. Wait the number of seconds in the Retry-After header before trying again. See Rate limits. |
INTERNAL_ERROR | 500 | Unexpected error on the server. The message is always generic and the body carries no errors or debug details. |
BAD_GATEWAY | 502 | An external service the API depends on failed. |
SERVICE_UNAVAILABLE | 503 | The API or a service it depends on is temporarily unavailable. During maintenance data.reason is MAINTENANCE. |
A 4xx status without its own code in this table returns BAD_REQUEST, and a 5xx status without its own code returns INTERNAL_ERROR. The HTTP status in the response is always the real one, so check both when you need to tell them apart.
Validation errors
A 422 lists each invalid field in data.errors, keyed by the field name:
{
"data": {
"code": "VALIDATION_FAILED",
"message": "The given data was invalid.",
"errors": {
"document_type": "The document_type field is required",
"document_number": "The document_number field is required"
}
},
"meta": {
"trace_id": "9f86d081884c7d659a2feaa0c55ad01568f3a1c2b4d5e"
}
}The value of each field is a message or a list of messages. When the request is rejected without a specific field, data.errors is an empty array or is not present.
Trace ID
Every response, successful or not, includes the X-Trace-Id header. In error responses the same value is also in meta.trace_id.
When you contact support about a failed request, send the trace ID. It identifies that exact request in the server logs.