InvarentDeveloper documentation

API error reference

Every error the API can return, and what to do about it.

Financial commands fail closed with a structured error envelope. Branch on error.code and error.retryable — never on the message text — and use help_uri to reach the matching entry on this page.

Error families
22
Reserved, not currently emitted
4
Anchor pattern
help_uri = this page + #code
Retry authority
error.retryable
01

The error envelope

Every failed command returns this body with the failing HTTP status, a request id for support, and a link back here. details is always an array and may be empty — read message first and treat the entries as extra detail when they are present.

{
  "error": {
    "code": "VALIDATION_ERROR",
    "message": "effectiveDate must be an ISO date",
    "request_id": "6f1c2a9e-3b7d-4c55-9e0a-2d4b8f1a7c30",
    "retryable": false,
    "details": [{ "path": "effectiveDate", "message": "Invalid date" }],
    "help_uri": "https://invarent.com/docs/errors#validation_error"
  }
}
Retry only when retryable is trueHonour Retry-After when presentQuote request_id in support requests
02

Error families

The canonical status is the one this family normally carries. An operation can return the same code with a more specific status, so branch on the code and retryable, not the status alone. Families marked Reserved are declared in the taxonomy but are not emitted by the current runtime; handle them defensively.

AUTHENTICATION_FAILED

HTTP 401

Authentication failed

Meaning
The request did not carry a usable credential. The bearer token, API key, or session is missing, malformed, expired, or revoked.
What to do
Re-authenticate or issue a new credential and retry once. Do not repeat the request with the same rejected credential; quote request_id to support if a fresh credential still fails.

help_uri https://invarent.com/docs/errors#authentication_failed

ACCOUNT_SELECTION_REQUIRED

HTTP 400

Account selection required

Meaning
The credential is valid for more than one account and the request did not say which account it applies to.
What to do
Resend the request with the x-account-id header naming one of the accounts the signed-in user belongs to (the portal sends it on every human request); when that account has more than one tenant, add x-tenant-id to choose the tenant. The headers only select among accounts the user is an active member of — naming an account the user does not belong to fails authentication instead.

help_uri https://invarent.com/docs/errors#account_selection_required

MFA_REQUIRED

HTTP 403

Multi-factor authentication required

Meaning
The signed-in user must complete a multi-factor authentication challenge before this action is allowed.
What to do
Complete the MFA challenge, then retry the same request. Do not treat this as a scope problem.

help_uri https://invarent.com/docs/errors#mfa_required

BILLING_ACCESS_RESTRICTED

HTTP 402

Billing access restricted

Meaning
The account's plan or subscription state does not permit this write. The specific reason is in error.details[].code: ACCOUNT_CLOSED, ACCOUNT_LINK_REQUIRED, ACCOUNT_SUSPENDED, LIMIT_REACHED, PAST_DUE, PAST_DUE_GRACE_EXPIRED, SUBSCRIPTION_CANCELED, SUBSCRIPTION_ENDED, SUBSCRIPTION_INACTIVE, SUBSCRIPTION_INCOMPLETE, SUBSCRIPTION_PAUSED, SUBSCRIPTION_PLAN_UNMAPPED, SUBSCRIPTION_REQUIRED, or SUBSCRIPTION_UNPAID.
What to do
Resolve the billing state named in details[].code, then retry. Reads and exports remain available while a write is restricted.

help_uri https://invarent.com/docs/errors#billing_access_restricted

AUTHORIZATION_DENIED

HTTP 403

Authorization denied

Meaning
The credential is valid but does not have the scope, role, or account membership this operation requires.
What to do
Check the key's scopes and the user's role. Use a credential with the required scope, or ask an account owner to grant access; retrying unchanged cannot succeed.

help_uri https://invarent.com/docs/errors#authorization_denied

AUTHENTICATION_ERROR

HTTP 401Reserved

Authentication error

Meaning
Reserved taxonomy member for a rejected credential. The runtime currently emits AUTHENTICATION_FAILED; handle both.
What to do
Treat exactly like AUTHENTICATION_FAILED: refresh the credential and retry once.

help_uri https://invarent.com/docs/errors#authentication_error

AUTHORIZATION_ERROR

HTTP 403Reserved

Authorization error

Meaning
Reserved taxonomy member for a permission refusal. The runtime currently emits AUTHORIZATION_DENIED; handle both.
What to do
Treat exactly like AUTHORIZATION_DENIED: correct the credential's scope or role before retrying.

help_uri https://invarent.com/docs/errors#authorization_error

TENANT_CONTEXT_ERROR

HTTP 403

Tenant context error

Meaning
The request's tenant context is missing, or it does not match the tenant the credential resolves to for this database transaction.
What to do
Retry with a credential for the intended tenant: an API key is bound to one tenant and cannot switch. A signed-in user may select among the tenants the API authorizes for that identity with the x-tenant-id header (and x-account-id for the account), but the database tenant context itself is always set by the server from the resolved credential, and a client-supplied value can never override it.

help_uri https://invarent.com/docs/errors#tenant_context_error

VALIDATION_ERROR

HTTP 400

Validation error

Meaning
The request body, query, or headers did not satisfy the operation's schema. error.details[] may name the offending location and reason when the operation knows them, but it may be empty: a missing Idempotency-Key, for example, is reported in error.message alone.
What to do
Read error.message first, then any details[] entries that are present — an entry carries what the operation knows, such as a location (path) and a reason (message, code, or issue). details may be empty, so never index into it blindly. A rejected request writes nothing, so the same external identifiers may be reused with a new Idempotency-Key.

help_uri https://invarent.com/docs/errors#validation_error

RESOURCE_NOT_FOUND

HTTP 404

Resource not found

Meaning
The addressed resource does not exist in this tenant, or this credential is not allowed to see it.
What to do
Verify the identifier and the tenant. A 404 for a resource that belongs to another tenant is intentional and must not be probed further.

help_uri https://invarent.com/docs/errors#resource_not_found

IDEMPOTENCY_CONFLICT

HTTP 409

Idempotency conflict

Meaning
The Idempotency-Key or source identity was already used with different content, so replaying it would create a conflicting financial effect.
What to do
Replay is decided on the canonical payload, not its bytes: the API parses the JSON body and sorts object keys recursively, so key order and whitespace do not matter, while any changed value or reordered array is a different payload. Reuse the key only for the same canonical payload; for changed content, send a new Idempotency-Key and reconcile with the event lookup first.

help_uri https://invarent.com/docs/errors#idempotency_conflict

CONCURRENCY_CONFLICT

HTTP 409

Concurrency conflict

Meaning
Either a concurrent write or version check lost the race (the stored record changed between the read and the write), a request with the same Idempotency-Key is still processing, or a uniqueness rule rejected the insert.
What to do
Re-read the resource and reconcile. A lost If-Match version check means the resource moved on: reapply your change against the fresh version before sending again. When error.retryable is true — the same Idempotency-Key is still processing, for example — wait and resend the same request with the same key. A lifecycle transition the resource's current state no longer permits, or a uniqueness rejection, will not clear by repeating the request: change the payload or the resource state first.

help_uri https://invarent.com/docs/errors#concurrency_conflict

ACCOUNTING_INVARIANT_VIOLATION

HTTP 422

Accounting invariant violation

Meaning
A ledger invariant refused the write: an unbalanced journal, a missing required dimension, or a reference to a resource that does not exist.
What to do
Fix the underlying accounting data; the whole transaction was rolled back. Retrying the same payload will fail the same way.

help_uri https://invarent.com/docs/errors#accounting_invariant_violation

PERIOD_NOT_OPEN

HTTP 409

Period not open

Meaning
The effective date falls in an accounting period that is not OPEN, so no new financial effect may be recorded there.
What to do
Post into an open period, or follow your close policy to reopen or adjust the closed period. A replay of an event that already posted is not blocked by this.

help_uri https://invarent.com/docs/errors#period_not_open

POLICY_VIOLATION

HTTP 403

Policy violation

Meaning
A tenant or platform policy forbids this action, such as editing a protected status directly or taking an action no auto-approval policy permits.
What to do
Use the controlled path the refusal points to (the lifecycle action, approval grant, or workflow), or change the policy as an authorized administrator. Some refusals are only a state race — a checkout still being confirmed, for example — and error.details[].code names the reason; retry those after the indicated wait. Otherwise repeating the same request cannot succeed.

help_uri https://invarent.com/docs/errors#policy_violation

APPROVAL_REQUIRED

HTTP 403

Approval required

Meaning
This action needs a content-hash-bound, single-use approval grant whose action matches the operation. The grant is missing, expired, already used, or bound to different content.
What to do
Request a grant for the exact content hash from a different authorized approver, then resend the unchanged payload. A POST grant does not satisfy POST_SOFT_CLOSE_ADJUSTMENT, and vice versa.

help_uri https://invarent.com/docs/errors#approval_required

SEPARATION_OF_DUTIES_VIOLATION

HTTP 403

Separation of duties violation

Meaning
The same actor prepared and approved the action, or requested and approved the grant. Separation of duties is enforced at the database and runtime layers.
What to do
Have a different authorized actor perform the approval. This control cannot be bypassed or overridden by configuration.

help_uri https://invarent.com/docs/errors#separation_of_duties_violation

RECONCILIATION_ERROR

HTTP 409Reserved

Reconciliation error

Meaning
Reserved taxonomy member for a subledger-to-GL reconciliation difference. The close interlock still refuses HARD_CLOSE while any subledger control reconciliation shows a non-zero difference.
What to do
Investigate the control-account difference before retrying; a HARD_CLOSE is refused while any subledger control reconciliation shows a non-zero difference.

help_uri https://invarent.com/docs/errors#reconciliation_error

PROVIDER_ERROR

HTTP 503

Provider error

Meaning
An upstream provider (for example the payment provider) failed, is not configured, or returned a payload the API cannot use.
What to do
When error.retryable is true, retry with backoff; a Retry-After header is not guaranteed for this family, so honor it only when it is present. Otherwise treat the provider payload or the integration's configuration as the cause and investigate before retrying.

help_uri https://invarent.com/docs/errors#provider_error

RATE_LIMITED

HTTP 429

Rate limited

Meaning
The caller exceeded its budget for this credential or operation. Two throttles surface as this family: the API request limit, which is retryable, and the marketing-lead anti-abuse limit, which is not.
What to do
Check error.retryable and the Retry-After header. When retryable is true, wait for the Retry-After the response carries, then retry with backoff and reduce concurrency rather than retrying immediately. When it is false (the marketing-lead throttle allows about five submissions per hour per source), do not auto-retry — wait out the window or contact support.

help_uri https://invarent.com/docs/errors#rate_limited

TRANSIENT_ERROR

HTTP 503Reserved

Transient error

Meaning
Reserved taxonomy member for a transient internal or dependency failure that is safe to retry.
What to do
Reserved: the current runtime does not emit it. If it ever appears, retry with exponential backoff, honoring Retry-After when it is present.

help_uri https://invarent.com/docs/errors#transient_error

INTERNAL_CONTROL_FAILURE

HTTP 500

Internal control failure

Meaning
An unexpected failure occurred, or a database control error had no more specific mapping. The failed request did not bypass any control.
What to do
Retry only when error.retryable is true. Otherwise capture request_id, x-request-id, and the UTC timestamp and contact support; do not resend blindly.

help_uri https://invarent.com/docs/errors#internal_control_failure