Skip to main content
Errors are JSON. The HTTP status is authoritative; the error code is the stable, machine-readable name to branch on. Human-readable message strings may change without notice — never match on them.

Envelope

  • error — stable machine code. Branch on this.
  • message — human-readable. For logs and UI; do not parse.
  • request_id — echo of the X-Request-Id response header. Include it in support tickets.
  • details — present when the error has structured context (validation field errors, conflicting state, etc.). Shape varies per code.
For validation failures (invalid_payload, invalid_query), details is { "formErrors": [...], "fieldErrors": { "<field>": ["message", ...] } }. fieldErrors keys are the offending fields, each mapped to an array of messages; formErrors holds errors that aren’t tied to a single field.
Timestamps throughout the API are ISO-8601 with an explicit +00:00 UTC offset (for example "2026-06-09T22:50:58.806+00:00"), not a trailing Z.
Always log request_id and the full response body when a request fails. The request id lets support trace a single call across the stack in under a second.

Authentication

See Authentication for key lifecycle.

Validation

Not found and gone

Conflict

Rate limits

Server errors

5xx responses are always retry-safe when paired with an Idempotency-Key on POSTs. GET, PATCH, PUT, and DELETE are naturally idempotent.

Worked examples

A validation error on POST /chatbots:
A cross-org access attempt:
The resource exists, but not under your org. We return 404 rather than 403 to avoid leaking the existence of resources in other orgs.