AUTHENTICATION_FAILED
HTTP 401Authentication 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 400Account 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 403Multi-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 402Billing 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 403Authorization 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 401ReservedAuthentication 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 403ReservedAuthorization 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 403Tenant 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 400Validation 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 404Resource 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 409Idempotency 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 409Concurrency 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 422Accounting 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 409Period 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 403Policy 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 403Approval 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 403Separation 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 409ReservedReconciliation 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 503Provider 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 429Rate 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 503ReservedTransient 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 500Internal 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