code, a human message, an actionable hint, and a
docs_url linking to the matching anchor on this page. Some errors add a param naming the
offending field and a typed details map.
code. It is stable across versions. Do not parse message; it is for humans and may
change. Where a code has no explicit status of its own, it answers 422, so treat 422 as the
general “understood but cannot be applied” rather than as one specific fault.
Kordio Control returns a different envelope and a different set of codes. See Kordio Control:
errors.
General
invalid_request
422 - The payload is malformed or missing required fields. When a specific field is at fault,
param and details.fields identify it.
unauthorized
401 - No valid access token was presented. Include a Bearer token from POST /oauth/token.
forbidden
403 - The token is valid but not permitted to perform this operation.
insufficient_scope
403 - The token lacks the scope this endpoint requires. Scopes do not imply each other:
ledger:write does not grant ledger:read. Re-request the token with both. See
Scopes.
not_found
404 - The resource does not exist. Verify the id and that it belongs to your tenant and ledger.
rate_limited
429 - Back off per the Retry-After header and retry.
internal_error
500 - Unexpected. Retry; if it persists, contact support.
Write semantics
missing_idempotency_key
422 - A write was sent without the required Idempotency-Key header. Supply a key unique per
logical request. See Idempotency.
unbalanced
422 - The transaction’s debits do not equal its credits in some currency. See
Double-entry.
currency_mismatch
422 - A posting’s currency does not match the account it targets. Every posting must use its
account’s currency.
unknown_account
422 - A posting references an account that does not exist. Create it before posting against it.
already_exists
409 - A resource with the same identifier or idempotency key already exists. Pick a different
id, or patch the existing resource.
already_reversed
409 - The transaction has already been reversed. Fetch it and inspect reversed_by.
immutable_field
409 - You tried to change a field that cannot change after creation, such as a posting’s
economic columns or an account’s currency.
insufficient_funds
422 - The source account would exceed its overdraft policy. The write was not applied.
account_closed
409 - The posting targets a closed account. Reopen nothing: post to a different account, or
correct the entry that closed it.
account_balance_nonzero
409 - You tried to close an account whose posted or pending balance is not zero. Move the
remaining value out first.
period_closed
409 - The value_date falls in a closed period. Book into the current open period, or reopen
the period.
period_close_imbalanced
422 - The trial balance at period_end does not net to zero in some currency, so the period
was not closed. details.residual_by_currency names the gap. Fix it, or close with
force: true, which records who forced it.
precondition_failed
409 - An If-Match or If-Unmodified-Since precondition was not satisfied.
duplicate_external_ref
409 - An external_ref with this (rail, kind, value) is already attached to another
transaction.
partial_refund_exceeds_original
422 - The refund amount plus prior partial refunds in this currency exceeds the original gross.
See details.remaining_by_currency.
refund_currency_required
422 - The original transaction is multi-currency, so you must pass currency to disambiguate
which leg you are refunding. See Multi-currency.
account_template_unknown
422 - The referenced account template does not exist. Create it first via
POST /v1/account_templates, or omit template to use raw account fields.
invalid_state
409 - The resource is not in a state that permits this operation.
run_in_progress
409 - A reconciliation run for this source is already queued or running. One at a time per
source. Wait for reconciliation.run_completed.
Credentials and lifecycle
rotation_in_progress
409 - The previous secret is still inside its 24-hour overlap window. Wait, or pass
?force=true to destroy it now.
webhook_endpoint_disabled
409 - The endpoint is disabled. Re-enable it via PATCH /v1/webhook_endpoints/{id} before
sending.
fresh_authentication_required
401 - This destructive operation requires a token issued within the last five minutes. Mint a
fresh one and retry.
tenant_suspended
403 - Your tenant is suspended. Contact support.
plan_required
402 - Your plan does not include this operation. Check Billing in the console.
OAuth
These follow RFC 6749 section 5.2 at the token endpoint.invalid_client
401 - The client_id or client_secret is wrong, or the client is disabled.
invalid_grant
422 - The grant_type or its parameters are invalid.
invalid_scope
422 - The requested scope is not granted to this client.
unsupported_grant_type
422 - Only client_credentials is supported today.
Next steps
Ledger concepts
The rules these codes enforce.
API reference
Which codes each endpoint can return.