Accountflow Developer next

Errors

Every error the API returns, as RFC 9457 problem details.

Every failure is an RFC 9457 problem document (application/problem+json) whose type URI ends in one of the slugs below, with a machine-readable error property carrying the same code. This page is a build gate: the server cannot ship an error code that is not documented here.

{
  "type": "https://api.accountflow.com/errors/resource-not-found",
  "title": "Resource Not Found",
  "status": 404,
  "detail": "Resource not found",
  "error": "resource_not_found",
  "requestId": "6f1c2d3e-…"
}
Code Status Meaning What to do
payload_too_large 413 An import request carries more lines than one request may hold (10 000 — the limit extension says so), or the request body is larger than 8 MiB (refused before it is parsed). Split the data into several requests and send them one after another: nothing queues, and a second import of the same kind for the same company while one is running is 409 conflict with reason: job_in_flight.
resource_not_found 404 The id doesn't exist within your reach. Deliberately indistinguishable from "exists but isn't yours" and "deleted". Check the id; check you're using the right client for the right organization.
duplicate_resource 409 The thing you're creating already exists (same company number in the org, same policy name, same assignment, duplicate rule). Fetch the existing resource instead, or change the distinguishing field.
conflict 409 Valid request, wrong state: an in-flight job for the same scope (jobId names it; reason: job_in_flight), a company not bound to the Api accounting system (reason: company_not_api_managed), an expired/incomplete upload slot, an archived policy, a GL line already reconciled this year, a missing GL mapping, an object in use (reason: *_in_use, inUse lists them), settings that changed since the version you named (currentVersion is the one now), an account template that changed since its preview, part of an account already on another intercompany link (reason: intercompany_account_owned, intercompany_account_shared, intercompany_account_split_differently, intercompany_slice_owned; definitionId and active name that link). Read reason and the extensions; resolve the state (poll the job, finish the upload, unmatch first, remove the dependent work; for settings, read them again and re-apply your change) and retry.
deleted_by_organization_cascade 409 The company was deleted as part of its organization's deletion — restoring it alone is impossible. Restore the organization instead.
validation_failed 400 The request is malformed: a required field is missing or blank, a value is out of range (pageSize outside 1–200, period outside 1–12), a parameter cannot be parsed. Fix the request; detail names the field, and the errors / parameter extensions say which.
unprocessable 422 The request is well-formed but semantically wrong: unknown role, foreign company on a rule, size over the type's cap, declared-vs-actual mismatch (an upload whose content is recognisably another type is deleted), an invalid organization number, an account code missing from the year's chart (reason: unknown_account_codes), a line id containing a forbidden character, an account template apply with warnings not confirmed (reason: confirmation_required, warnings lists them). The detail explains the rule that failed; the errors extension lists the offending lines; for confirmation_required, have a person confirm the warnings and send them as confirmedWarnings.
malware_detected 422 The uploaded file failed the virus scan at complete_document_upload. The file is deleted and no document is created. Do not retry the same file. A clean file can be uploaded to the same slot while its URL is valid, or through a new upload.
unauthorized 401 Missing, expired, or invalid token. WWW-Authenticate distinguishes only no token (a bare Bearer challenge) from a token that was rejected (error="invalid_token") — it does not say whether the rejected token was expired, mis-audienced or malformed. Fetch a fresh token; check audience and issuer.
forbidden 403 Authenticated, but this action is denied. Check the client's provisioning in Accountflow.
capability_denied 403 This kind of principal can never do this (e.g. an MCP sign-in calling /v1; an interactive session writing). Use an API client (client credentials) for /v1.
insufficient_scope 403 The token lacks a required scope — WWW-Authenticate names it (scope="..."), as does the requiredScope extension. Request the scope (interactive) or have it granted (machine clients).
rate_limited 429 Plan quota exceeded. Retry-After (and retryAfterSeconds) say when to come back. Back off per Retry-After; consider the premium plan for sustained volume.
idempotency_key_missing 400 Every mutation requires an Idempotency-Key header. Send a unique key per logical operation; retries reuse the same key.
idempotency_key_reused 422 The key was used before with a different request body (within the 24-hour replay window, for the same operation). Never reuse keys across different operations; generate a UUID per logical action.
idempotency_in_flight 409 The same key's first request is still executing. Retry-After is set. Wait and retry with the same key — you'll get the stored response.
invalid_cursor 400 The cursor is expired, tampered with, from another client, or from a request with different filters. Restart from the first page. Never modify or share cursors.
method_not_allowed 405 The path exists; the verb doesn't. Check the reference.
internal_error 500 Our bug. The response's requestId lets support find it immediately. Retry with the same Idempotency-Key (safe); report the requestId if it persists.
not_implemented 501 Reserved. No operation returns it today; the slug stays in the catalog so that the code can never surface it undocumented. If you ever see it, report the requestId.
service_unavailable 503 A dependency (e.g. the authorization backend, the import engine, the semantic layer, the virus scanner at upload completion — the uploaded file is kept) is unavailable. Fails closed — never wrong data. Retry-After is set. Retry with backoff; mutations are idempotent-safe to retry with the same key.
unsupported_media_type 415 The declared content type isn't accepted (document uploads validate against the allowlist; the supported extension lists it). GET the reference for accepted types and size caps.

Problem extension fields

Beyond the RFC 9457 members (type, title, status, detail, instance) every problem document carries error (the slug above) and requestId (the request's correlation id — the same value as the X-Request-Id response header). The spec declares these extensions on the operations that can produce them; each is present only when it applies:

Extension Type Present on Meaning
reason string, snake_case conflict, unprocessable The specific rule that fired, e.g. job_in_flight, company_not_api_managed, unknown_account_codes, lines_in_use, account_in_use, confirmation_required, intercompany_slice_owned. Branch on error first, then on reason.
currentVersion string conflict on a settings write The settings' version now; read them again before re-applying your change.
warnings array of strings unprocessable with reason: confirmation_required The account-template warnings still to be confirmed (TEMPLATE_CHANGED, DOCUMENTATION_REQUIREMENT_REMOVED, AUTO_APPROVE_ENABLED).
definitionId, active, counterparty UUID, boolean, string conflict with reason: intercompany_* The intercompany link that already has that part of the account, whether it is active, and its counterparty.
inUse array of {id, dependencies} conflict with reason: *_in_use The objects (by your id or key — never an internal id) that user work depends on, and what depends on them.
accountCodes array of strings unprocessable with reason: unknown_account_codes The codes missing from the year's chart of accounts.
errors array of error items (below) validation_failed, unprocessable Field-level detail, up to 100 items.
limit integer payload_too_large The cap that was exceeded (lines per request).
jobId UUID conflict with reason: job_in_flight, idempotency_in_flight The job or request that is blocking this one — poll it.
retryAfterSeconds integer rate_limited, service_unavailable, idempotency_in_flight The Retry-After header as a number.
requiredScope string, resource:action insufficient_scope The scope the token lacks.
parameter string validation_failed, invalid_cursor The query or path parameter at fault (pageSize, cursor, year, …).
supported array of strings unsupported_media_type, validation_failed The accepted values when the request named one outside them (content types, filter values).

The errors item — one shape everywhere

{ "field": "lines[12].amount", "message": "amount is required", "index": 12 }

Every validation_failed and unprocessable response uses this one item shape; there is no per-endpoint variant.