View Markdown

Errors

When a request fails, the API answers with application/problem+json (RFC 9457): one shape for every error, with a stable code that has its own page here. The response’s doc_url is that page.

{
  "type": "https://usekabu.com/docs/errors/invalid_request",
  "title": "Invalid request",
  "status": 400,
  "code": "invalid_request",
  "detail": "The body does not match the contract.",
  "hint": "Fix the fields listed in errors and resend.",
  "param": "/title",
  "errors": [{ "param": "/title", "code": "invalid_request", "detail": "…" }],
  "retryable": false,
  "request_id": "req_01J9Z…",
  "doc_url": "https://usekabu.com/docs/errors/invalid_request"
}
Field What it is
code Stable, machine-readable: branch on it
status The HTTP status, also the response’s
detail What went wrong with this request, for people
hint The next step, in one sentence an agent can act on
param The field at fault, as a JSON pointer, such as /ask/options/2/label
errors When several fields fail: one {param, code, detail} each
retryable Whether the same request may succeed later unchanged
request_id Quote it to support

Handling errors

  • Branch on code, and on status for a code you do not know: new codes can appear.
  • Retry only what can succeed: rate_limited after its Retry-After, idempotency_key_in_use after a moment, and a 5xx with backoff. Send retries with the same Idempotency-Key, so nothing happens twice.
  • Never retry a 4xx unchanged otherwise: fix the request, using hint and param.

Every code

Code Status Means
invalid_request 400 A request or a value in it breaks one of the contract’s rules: a missing field, a value too long, an option that does not exist.
unknown_parameter 400 The request has a field or query parameter the contract does not define. Request bodies are closed, so a typo never passes silently.
unauthorized 401 No valid credential came with the request: the key is missing, mistyped or revoked, or a signed-in session has expired.
forbidden 403 The credential is valid but may not do this: the key lacks a scope, is bound to another project, or the operation takes another kind of credential.
self_response_forbidden 403 A key that sends messages tried to act as a person: to answer an ask, mint an answer link or pair a recipient. No agent may answer itself.
incompatible_scopes 400 A key was to hold messages:write together with answers:delegate or steer:write. Asking and answering never share a key.
not_found 404 No such resource, or none this key may see: Kabu answers the same for both, so ids in other accounts stay secret.
idempotency_key_reused 422 The Idempotency-Key was used before with a different request body. A key names one request; a different request needs a new key.
idempotency_key_in_use 409 A request with the same Idempotency-Key is still being handled. Wait a moment, then send the same request again.
already_settled 409 The ask was already answered, expired or was cancelled, so it cannot be answered again. The response includes the settled message.
ask_expired 410 The ask’s deadline has passed, so it can no longer be answered.
lease_lost 409 Steering, a preview: the lease on a claimed steering instruction is no longer current, so it cannot be acknowledged with that token.
invalid_ack_transition 409 Steering, a preview: an acknowledgement would move a steering instruction to a state it cannot reach from its current one.
rate_limited 429 Too many requests in a short time, or the agent is paused for sending near-identical messages. Wait for Retry-After, then send the same request.
quota_exceeded 429 The account’s monthly notifications are used up, or it reached the cap on projects or agents created by name. Retrying will not help.
payload_too_large 413 The request body or file is too big: JSON bodies are at most 64 KiB, and a direct upload at most 25 MiB.
unsupported_media_type 415 The request’s Content-Type is not one this operation takes: JSON for most, multipart/form-data for a direct upload.
checkpoint_expired 410 The events checkpoint is older than events are kept. Start again from a new checkpoint, the current state, then newer events.
checkpoint_filter_mismatch 400 The events checkpoint was issued for other filters. A checkpoint resumes only the reading it came from.
upload_expired 410 The presigned upload was not finished in time; its bytes never became media. Create a new upload.
media_not_ready 400 A message attaches media that is not ready: still uploading, failed, or from another project.
unsupported_schema_keyword 400 The action’s args_schema uses a JSON Schema keyword outside the supported set, such as format or $dynamicRef.
invalid_receipt 422 The receipt does not verify: its signature, issuer, org or mode does not match. Send it exactly as Kabu returned it.
attempt_expired 409 Steering, a preview: the window to report the outcome of a steering instruction has closed.
precondition_failed 412 The resource changed since you read it (If-Match), or an upload is already finalised and cannot change.
session_ended 409 The session has ended, so it takes no new messages or answers. Start a new session.
project_in_use 409 A project cannot be deleted while an API key is bound to it or to one of its agents.
not_implemented 501 The operation is in the contract but not available on this server yet.
internal_error 500 Something failed on Kabu’s side. Retry with the same Idempotency-Key; if it persists, tell support with the request_id.