Skip to content

Responses and errors

The response envelope, the error object and its codes, request ids and size limits.

Updated

Every operation answers JSON in the same envelope, whether it succeeds or fails, so one piece of code can read any answer. The one exception is text answers for AI agents, which you ask for.

The envelope

Field On success On failure
success true false
data The result: a record, a page, or what the operation declares. null
error null The error object.
metadata { "requestId": "…" } { "requestId": "…" }

A success, here from account.apiKeys.delete:

{
  "success": true,
  "data": { "id": "exampleClientId0001", "deleted": true },
  "error": null,
  "metadata": { "requestId": "00000000-0000-4000-8000-000000000001" }
}

The status code tells success from failure too: successes answer 200, failures 4xx or 5xx. The TypeScript SDK resolves with the whole envelope and throws ApiError for any other status; the Rust SDK returns data.

The error object

A failure, here a request without a valid credential:

{
  "success": false,
  "data": null,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "A valid access token is required.",
    "retryable": false,
    "data": {}
  },
  "metadata": { "requestId": "00000000-0000-4000-8000-000000000002" }
}
Field Meaning
code The failure code, stable across releases. Branch on it.
message What went wrong, for people. It never contains input values. Don’t parse it.
retryable Whether repeating the same request may succeed. See Retries.
data Diagnostics the code declares. Empty for most codes.

For INVALID_INPUT, data.issues lists up to 10 problems, each with a path, an RFC 6901 JSON Pointer to the refused field (empty for the whole input), and a message.

Common codes

These codes can come from any service. Each operation’s page in the API reference lists the codes it answers, by status.

Status code retryable Meaning
400 INVALID_INPUT false The request does not match the published schema.
401 UNAUTHORIZED false A valid access token is required. See 401 or 403.
403 FORBIDDEN false The token does not authorize this operation.
404 NOT_FOUND false Nothing matches the path.
405 HTTP_METHOD_NOT_ALLOWED false The HTTP method is not supported for this resource.
413 REQUEST_TOO_LARGE false The request exceeds the allowed size. See Size limits.
415 UNSUPPORTED_MEDIA_TYPE false The request content type is not supported. Send JSON bodies as application/json.
429 RATE_LIMITED true The request rate limit was exceeded. Wait the seconds in Retry-After.
500 INTERNAL_ERROR false The service could not complete the operation.
502 OUTCOME_UNKNOWN false The operation may have been applied. Check its result before repeating it.
503 UPSTREAM_UNAVAILABLE true The upstream service could not complete the request.
504 UPSTREAM_TIMEOUT true The upstream service did not respond before its deadline.

Services add their own codes for their own rules, such as API_KEY_NOT_FOUND (404) in Account or VERSION_CONFLICT (409) in Raíz.

Request ids

Every response carries an X-Request-Id header, and the envelope repeats it as metadata.requestId. Log it with every failure, and include it when you report a problem.

Responses to 429, and to some other failures as their reference shows, also carry Retry-After: the seconds to wait before another attempt.

Size limits

Each operation accepts a request and returns a response of up to a maximum size, which its page in the API reference shows under Limits. A larger body is refused with 413 REQUEST_TOO_LARGE; on MCP, the limit bounds the tool call’s input.

Most operations accept a body of up to 32 KiB. Operations that carry files accept more, such as raiz.knowledge.create (12 MiB) and raiz.contacts.import (16 MiB). Responses range from 256 KiB, as for account.organization.get, to 16 MiB for account.invoiceDocuments.get. The Rust SDK treats a response larger than its operation’s limit as invalid.

In the API’s OpenAPI document (https://api.getarbol.com/v1/<service>/openapi.json), each operation carries its limits in bytes, as x-max-body-bytes and x-max-output-bytes.

Text answers for AI agents

Some integration operations, such as SURA’s, Nueva EPS’s and ADRES’s, take an optional agentMode. With agentMode: true, they answer concise Spanish text meant for an AI agent, with the same authorization. Depending on the operation, the text comes as text/plain instead of JSON, or inside the envelope, in data.text; each operation’s page in the reference says which. Leave it out to get the structured result.

Type to search…

↑↓ navigate↵ selectEsc close