Errors

The one flat error envelope every endpoint returns, the status codes it is paired with, and which refusals are worth retrying.

Every error response has the same flat shape:

{
  "error": "VALIDATION_ERROR",
  "message": "name is required",
  "details": [{ "field": "name", "issue": "required" }]
}

error is a stable machine-readable code, message is human-readable, and details is optional. The envelope is never nested and never carries a success flag — branch on the HTTP status and on error, never on the presence of a payload.

Status codes

statusmeaning
400the request is malformed or a field is missing
401not authenticated — missing, malformed, expired or revoked token
403authenticated, but not permitted; on the public API this is almost always INSUFFICIENT_SCOPE
404the resource does not exist
409a conflict — a concurrent update was lost, or the resource is already in the requested state
422the request is well-formed but cannot be processed
429the token’s rate limit was exceeded
500an unexpected failure on our side
503the service is still starting — retryable

INSUFFICIENT_SCOPE is the refusal to design for

Because the public API is default-deny, the most common error a working integration meets is not a validation failure — it is a scope refusal. A token reaches only the entities and actions it was issued for, and everything else answers 403 INSUFFICIENT_SCOPE with the entity and action named in the message. See Authentication for the scope model and the exact body.

Treat it as a configuration error, not a transient one: it is deterministic for a given token and endpoint, and it clears only when the token is re-issued with the missing scope.

What is worth retrying

  • 429 and 503 are transient. Back off and retry.
  • 5xx other than 503 may be transient; retry with backoff and a ceiling.
  • 400, 401, 403, 404, 409, 422 are not. The same request will fail the same way. 403 INSUFFICIENT_SCOPE in particular is a token that needs re-issuing, and retrying it only spends your rate limit.

Code lists in the reference are samples, not closed unions

Individual endpoints in the reference document the error codes that endpoint’s service actually emits. Those lists are a sample of what you are likely to see, not an exhaustive union — a client must handle an unrecognised error value by falling back to the HTTP status.

See also

← All documentation