Errors

The error envelope, its codes, and what each status means.

Every refusal on /api answers one envelope. request_id matches the request log entry, so you can quote it when something looks wrong. errors is an array, because a validation may reject more than one field at once.

Error envelope
{
  "type": "error.list",
  "request_id": "01j9…",
  "errors": [
    { "code": "invalid_field", "message": "expected an absolute origin", "field": "FIKADESK_PUBLIC_URL" }
  ]
}

Status codes

StatusMeaning
400The request line or a query parameter is malformed, or a cursor does not match the sort it was minted under.
401No credential, or an upload token that does not verify.
403The credential does not carry the permission this route needs.
404No row with that id in this workspace.
409The row moved under the request, or a key is still in flight.
422The body names something the workspace refused, or the idempotency key was reused with a different body.
429Rate limited; Retry-After says when.

Two statuses show up only on the routes that need them. Read-only collections answer 405 with an Allow header naming the methods they take. A contact that was merged away answers 410 with a Link header naming the surviving contact.

Common codes

  • invalid_field is the validation catch-all; field names the offending path.
  • body_too_long when a body exceeds the cap.
  • too_many_attachments when a reply names more attachments than the limit.
  • not_found and forbidden and conflict mean what they say.
  • rate_limited, idempotency_key_reused, idempotency_key_in_flight come from their middleware.
  • invalid_token when a hosted-source importer refuses a token.

The receiver and webhook surfaces outside the tenant stack answer bare statuses with no envelope. A transport or a bridge that cannot prove it is one of ours learns nothing from the answer, which is the point.