Skip to content
Apier
Apier.no

Error reference

The canonical Apier error reference — the standard error envelope, the explanation and handover schemas, and the full structured error_code catalogue.

[Cite this as: Apier.no Docs v0.1.0 — last updated 2026-06-23]

Every Apier API error returns the same structured envelope, so your agent can branch on a machine-readable error_code instead of string-matching prose. This page is the canonical reference for that envelope, the explanation object it carries, and every error_code the API can emit.

The error envelope

Every 4xx and 5xx response from /api/v1/* has the same top-level shape — { success: false, error_code, explanation, _meta }:

{
  "success": false,
  "error_code": "AUTH_NO_DELEGATION",
  "explanation": {
    "summary": "Ingen aktiv systembruker-delegering finnes for 999999999.",
    "why": "Konsumenten har ingen aktiv systembruker-delegering hos Altinn for 999999999.",
    "fix_steps": [
      "Opprett en systembruker via altinn.no/systembruker og knytt den til integrasjonen.",
      "Be en signaturberettiget godkjenne delegeringen i Altinn.",
      "Gjenta forespørselen når delegeringen vises som aktiv."
    ],
    "relevant_link": "https://altinn.no/systembruker",
    "legal_basis": null,
    "handover": {
      "who": "company_admin",
      "where": "https://altinn.no/systembruker",
      "what": "Opprette systembruker og godkjenne delegering for 999999999.",
      "why": "Uten delegering har systembrukeren ingen rettigheter på vegne av organisasjonen."
    }
  },
  "_meta": {
    "rulebook_version": "2026.6.0",
    "data_freshness": "2026-06-23T08:00:00Z"
  }
}

success is always false on an error. error_code is a stable machine string from the catalogue below. explanation is human-and-agent readable, and all of its prose is Norwegian bokmål. _meta rides on errors too, so your agent can diff the rulebook_version it last saw against the one that just failed. Every value above is synthetic — 999999999 is the documentation fixture organisation number.

The explanation object

explanation always carries a summary; every other field is optional and present only when it applies. The type is ApiErrorExplanation in src/types/api.ts.

FieldRequiredMeaning
summaryRequiredOne-sentence statement of what went wrong.
whyOptionalLonger explanation of the cause, in Norwegian bokmål.
fix_stepsOptionalOrdered, imperative next steps the caller can take.
relevant_linkOptionalPublic Altinn / Skatteetaten / Brønnøysund / Apier-docs URL for this error.
legal_basisOptionalLovdata-style legal reference when the error maps to a statute.
detailsOptionalField-level validation problems as [{ field, message }].
handoverOptionalPresent when a human must act before the agent can proceed (see below).

The handover object

When an agent reaches a boundary it cannot cross on its own — an Altinn role that isn't delegated, a Maskinporten scope that isn't granted, or an error that needs Apier triage — explanation.handover names who must step in. It is absent for errors the agent can resolve itself by retrying, adjusting input, or waiting.

FieldMeaning
whoThe human role to escalate to — one of company_admin, accountant, altinn_user, apier_support.
whereA stable URL or location where that person performs the action.
whatThe concrete action they must take.
whyWhy the agent itself cannot complete it.

error_code catalogue

The authoritative list is the EXPLAINER_ERROR_CODES tuple in src/types/explainer.ts38 codes, grouped below by theme. Each code's enriched explanation (summary, fix steps, handover) is produced by the Compliance Explainer in src/lib/compliance/explainer.ts.

Auth & delegation

CodeMeaning
AUTH_INSUFFICIENT_ROLEThe system user lacks the required Altinn role for this action.
AUTH_NO_DELEGATIONNo active Altinn system-user delegation exists for the organisation.
AUTH_MISSING_DELEGATIONSemantic alias of AUTH_NO_DELEGATION — same explanation, surfaced by the sandbox ?simulate_error= flow.
AUTH_EXPIRED_TOKENThe one-time approval token was valid earlier but its lifetime has elapsed.

Validation & lookup

CodeMeaning
VALIDATION_FAILEDThe request failed schema validation at the API boundary — correct the input field.
NOT_FOUNDThe requested resource was not found in the source register.
COMPANY_NOT_FOUNDThe organisation number was not found in Brønnøysund — deregistered, not yet registered, or wrong.
DEADLINE_PASSEDThe filing deadline had already passed at call time.
REQUEST_TOO_LARGEThe request body exceeds the 256 KB limit for write calls.

Scope & plan

CodeMeaning
SCOPE_MISSINGThe required Maskinporten scope is not in the consumer's grant.
SCOPE_INSUFFICIENT_FOR_ACTIONThe active delegation does not cover every Maskinporten scope the action type requires (see missing_scopes).
PLAN_INSUFFICIENTThe action is unavailable on the live path — either the tier does not cover writes, or the action type is not live-enabled yet.

Idempotency

CodeMeaning
IDEMPOTENCY_KEY_REQUIREDThe write call requires an Idempotency-Key header.
IDEMPOTENCY_KEY_MISMATCHThe same Idempotency-Key was reused with a different request body.
IDEMPOTENCY_IN_PROGRESSAn earlier request with the same Idempotency-Key is still being processed.

Approval & risk

CodeMeaning
APPROVAL_TOKEN_REQUIREDThe write needs a time-boxed, human-approved token; rejected before any upstream call.
APPROVAL_TOKEN_INVALIDThe approval token is unknown or malformed — existence is deliberately not disclosed.
APPROVAL_TOKEN_USEDThe approval token has already been consumed — single-use, even on a failed attempt.
APPROVAL_TOKEN_EXPIREDThe approval token passed its short lifetime before the request was sent.
APPROVAL_TOKEN_MISMATCHThe token was minted for a different action_id or organisation than the request.
RISK_ELEVATEDThe anomaly detector requires human approval; obtain an approval token and retry.

Execution & circuit

CodeMeaning
EXECUTION_FAILEDA valid, approved submission could not be completed against the upstream.
EXECUTION_TIMEOUTThe submission timed out; whether it registered upstream is unknown until polled.
EXECUTION_DEADLINE_EXCEEDEDThe request exceeded Apier's 8-second total execution budget.
EXECUTION_CIRCUIT_OPENApier's circuit breaker is open for this upstream; new requests are rejected for about 30 seconds.
RETRY_BUDGET_EXHAUSTEDApier exhausted its retry budget (up to three attempts) without success.
FOLLOWUP_REQUIREDThe action is partially complete; read outcome.followup_action to finish it.

Government & upstream

CodeMeaning
UPSTREAM_UNAVAILABLEThe named upstream service is unavailable or timed out.
GOVERNMENT_API_ERRORThe submission reached the upstream but was rejected with an operational error.
GOVERNMENT_RATE_LIMITEDThe government API responded 429; Apier respects the quota and did not execute the call.
GOVERNMENT_UNAVAILABLEThe government API returned a 5xx or dropped the connection; Apier retried and gave up.
GOVERNMENT_VALIDATION_REJECTEDThe government API rejected the content — format, totals, or missing required fields.
MASKINPORTEN_AUTH_FAILEDMaskinporten rejected Apier's token request — server-side; the client cannot fix it.
ALTINN_DELEGATION_MISSINGAltinn returned 401/403 — Apier's system user has no active delegation for the organisation.

Rate limiting

CodeMeaning
RATE_LIMIT_EXCEEDEDThe API key hit its per-minute rate limit for this route and tier.

Sandbox

CodeMeaning
SANDBOX_TEST_KEY_REQUIREDA sandbox magic feature (X-Apier-Simulate or ?as_of=) requires the synthetic sandbox bearer, not a real key.

General & fallback

CodeMeaning
INTERNAL_ERRORAn unexpected internal error on Apier; the cause is not in the request content.
UNKNOWNThe error could not be classified against a known code — the safe fallback.

Get a live explanation

Every code above can be expanded into a full explanation object on demand. POST /api/v1/explain is a zero-auth endpoint (no API key needed) that takes an error_code plus an optional context and returns the canonical explanation — the same object the API attaches to a real error. It makes no upstream calls and stores no data.

curl -X POST https://apier.no/api/v1/explain \
  -H "Content-Type: application/json" \
  -d '{ "error_code": "AUTH_NO_DELEGATION", "context": { "org_number": "999999999" } }'

The response wraps the explanation in the standard success envelope:

{
  "success": true,
  "data": {
    "explanation": {
      "error_code": "AUTH_NO_DELEGATION",
      "summary": "Ingen aktiv systembruker-delegering finnes for 999999999.",
      "why": "Konsumenten har ingen aktiv systembruker-delegering hos Altinn for 999999999.",
      "fix_steps": [
        "Opprett en systembruker via altinn.no/systembruker og knytt den til integrasjonen.",
        "Be en signaturberettiget godkjenne delegeringen i Altinn.",
        "Gjenta forespørselen når delegeringen vises som aktiv."
      ],
      "relevant_link": "https://altinn.no/systembruker",
      "legal_basis": null,
      "handover": {
        "who": "company_admin",
        "where": "https://altinn.no/systembruker",
        "what": "Opprette systembruker og godkjenne delegering for 999999999.",
        "why": "Uten delegering har systembrukeren ingen rettigheter på vegne av organisasjonen."
      }
    }
  },
  "_meta": {
    "rulebook_version": "2026.6.0"
  }
}

The context fields (org_number, scope, role, field, upstream_system) are interpolated into the Norwegian text wherever the template references them; omit them and the explanation falls back to a neutral Norwegian noun. The standard trust _meta block rides on the response alongside rulebook_version.

Going deeper

This page is the canonical index. For a walkthrough of handling these errors in agent code — retry strategy, the human-handover boundary, and worked examples — see Error handling and the Compliance Explainer.