Errors

One envelope, stable machine-readable codes, and what each status means.

Every error, from every endpoint, has the same shape:

{
  "error": {
    "code": "agents.not_found",
    "message": "Agent not found.",
    "details": null
  }
}
  • code — stable and machine-readable. Branch on this.
  • message — for a human. It may be reworded between releases; do not match on it.
  • details — present when there is structure worth sending, such as which field failed validation. Absent otherwise.

Stack traces are never returned in production.

Status codes

StatusMeaningWhat to do
400The request is malformed or the operation is not valid in this stateRead code — it says which
401Missing, expired or invalid credentialsRefresh the token, or check your credentials
403Authenticated, but not allowedThe role or scope is insufficient — this will not change on retry
404No such object in this organizationSee below
409Conflict with existing stateUsually a duplicate
422Validation faileddetails names the field
429Rate limitedBack off — see rate limits
5xxOur problemRetry with backoff; if it persists, it is not you

Code families

Codes are namespaced by the area they come from. There are around 95 of them; these are the ones you will actually meet.

auth.*

CodeMeaning
auth.not_authenticatedNo credentials were sent
auth.invalid_credentialsWrong email or password
auth.invalid_tokenThe access token is malformed or expired
auth.account_inactiveThe account is disabled
auth.email_takenAlready registered
auth.weak_passwordDoes not meet the policy

org.*

CodeMeaning
org.missing_headerAn org-scoped route was called without X-Org-Id
org.forbiddenYour role in this organization does not permit this
org.not_foundNo such organization, or you are not a member

Resource families

agents.*, kb.*, conversations.*, tools.*, channels.*, inbox.*, workflows.*, contacts.* and webhooks.* each follow the same pattern: *.not_found for a missing object, plus codes for the states that are specific to them — agents.no_version when an agent has never been published, workflows.not_paused when you resume a run that is not waiting, channels.bad_signature on a webhook that fails verification.

llm.*

CodeMeaning
llm.provider_unavailableThe provider could not be reached, or no key is configured
llm.provider_errorThe provider rejected the request
llm.unknown_providerThe agent names a provider that does not exist

llm.provider_unavailable is worth handling explicitly. It is the one that fires when a provider key is missing — and the symptom is that every turn fails, not that answers get worse.

Validation errors

422 carries the offending fields:

{
  "error": {
    "code": "validation_error",
    "message": "Request validation failed.",
    "details": [
      { "loc": ["body", "temperature"], "msg": "Input should be less than or equal to 2", "type": "less_than_equal" }
    ]
  }
}

Handling them

const res = await fetch(url, { headers });
if (!res.ok) {
  const { error } = await res.json();
  switch (error.code) {
    case "auth.invalid_token":
      return refreshAndRetry();
    case "llm.provider_unavailable":
      return degradeGracefully();     // do not retry in a loop; the key is missing
    default:
      throw new Error(`${error.code}: ${error.message}`);
  }
}

Retry 429 and 5xx with backoff. Do not retry 4xx — nothing about the request will have changed.