Errors
RFC 9457 problem details with stable machine-readable codes
Every error — from any endpoint, any status — is a flat
RFC 9457 body with content type
application/problem+json:
Match on code, not on text
code is the contract: dotted, namespaced (<domain>.<outcome>), and never
reused for a different meaning. title is for humans and may be reworded;
status alone is too coarse (several unrelated conflicts all map to 409).
Switch on category for retry policy
When you want one branch per kind of failure rather than per code, use
category. It is deliberately small and stable:
Every type URL resolves
Follow the type link, or browse
GET /errors for the whole catalog and
GET /errors/{code} for one entry. The catalog is generated from the same
registry the API raises from, so it is never out of date. It is
unauthenticated — it is the documentation. Each API Reference endpoint also
documents exactly the errors it can return, with examples.
Structured causes
Errors that point at a specific cause carry one extra array.
invalid_params locates a bad request field or header:
422 validation.request_invalid is the schema-validation failure and always
carries invalid_params, one entry per failing field. Errors about the state
of a resource rather than a field carry state_errors in the same shape, with
resource and resource_id in place of field.
For POST /v1/messages/batch in permissive mode, each failing position
carries this same problem shape inside its own items[].error object, so a
per-item failure reads exactly like a top-level one.
When you contact support
Quote the request_id — it links your response to our internal logs exactly.