Errors

The standard error envelope, request IDs, error codes, and retry guidance.

API errors use one standard envelope:

{
  "status": "error",
  "code": "validation_error",
  "message": "Validation failed",
  "request_id": "F7qLx0e8hAA=",
  "details": {
    "status": "must be one of draft, approved, void"
  }
}

request_id is echoed from x-request-id when available. Include it in support requests and logs.

Common codes

HTTPCodeRetry?Meaning
400invalid_idempotency_keyNoIdempotency-Key is blank, too long, or repeated in headers.
401unauthorizedAfter fixing authMissing, expired, revoked, or invalid bearer token.
403forbiddenNoToken is valid but lacks the required scope or policy permission.
404not_foundNoThe resource does not exist in the authenticated tenant. Cross-tenant lookups also return 404.
409conflictUsually noResource state does not allow the requested transition.
409idempotency_key_conflictNoThe key was already used for a different request fingerprint.
409idempotency_key_in_progressYesThe first request for this idempotency key has not completed.
422validation_errorAfter fixing payloadRequest body or query parameters failed validation.
422period_closedAfter period unlockThe accounting period is locked for the requested mutation.
429rate_limitedYesRetry after the retry-after header value.
500server_errorYesUnexpected server failure.
500workflow_crashedYesA workflow raised unexpectedly.

Some extension and deployment endpoints return endpoint-specific codes such as deploy_failed, dev_deploy_failed, rollback_failed, promote_failed, and hook_error. They still use the same envelope.

Retry guidance

Retry:

  • 429 rate_limited after retry-after.
  • 409 idempotency_key_in_progress with the same request and same key.
  • 5xx failures with an Idempotency-Key on POST requests.

Do not retry unchanged:

  • 401 unauthorized.
  • 403 forbidden.
  • 404 not_found.
  • 409 idempotency_key_conflict.
  • 422 validation_error or 422 period_closed.

Success envelopes

Public resource endpoints use record and list envelopes — status and message at the top level are reserved for error envelopes and legacy compatibility responses. Record reads and mutations return {id, object, data}; deletes and voids return a deleted-object envelope with deleted: true (and voided: true where appropriate); lists return {object: "list", data, pagination}.