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-07-31]

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."
    ],
    "summary_en": "No active system-user delegation exists for 999999999.",
    "why_en": "The consumer has no active system-user delegation in Altinn for 999999999.",
    "fix_steps_en": [
      "Create a system user via altinn.no/systembruker and connect it to the integration.",
      "Ask a person with signing authority to approve the delegation in Altinn.",
      "Retry the request once the delegation shows as active."
    ],
    "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: its summary / why / fix_steps prose is Norwegian bokmål, carried alongside English summary_en / why_en / fix_steps_en siblings (see below). _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.

The Norwegian summary / why / fix_steps come with English summary_en / why_en / fix_steps_en siblings carrying the same guidance, so an English-language agent gets actionable text without translating the bokmål. The handover and legal_basis fields stay Norwegian / Lovdata-native.

FieldRequiredMeaning
summaryRequiredOne-sentence statement of what went wrong (Norwegian bokmål).
summary_enOptionalEnglish translation of summary.
whyOptionalLonger explanation of the cause, in Norwegian bokmål.
why_enOptionalEnglish translation of why.
fix_stepsOptionalOrdered, imperative next steps the caller can take (Norwegian bokmål).
fix_steps_enOptionalEnglish translation of fix_steps — same steps, in the same order.
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.

Machine-actionable fields

Alongside explanation, a catalogued error carries up to four top-level machine-actionable fields — siblings of error_code, not nested inside explanation. They let an agent decide whether to retry and what to change without parsing prose:

FieldTypeMeaning
retryablebooleantrue → repeating the same request after a short backoff can plausibly succeed (transient upstream, rate limit). false → an identical retry is wasted; change the input, the credential, or hand over to a human first.
fix_hintstringA single terse imperative remediation for error_code — the one-line form of explanation.fix_steps, safe to branch on without walking an array. Written in English (the machine-facing lingua franca, like the MCP remediation strings), unlike the Norwegian-primary summary / why / fix_steps.
fix_hint_enstringGuaranteed-English accessor for the fix hint; present whenever fix_hint is. Because fix_hint is already English today, fix_hint_en equals it — it is the stable seam that lets a future localized (bokmål) fix_hint land without breaking agents that pinned to the English text.
docs_urlstringStable documentation URL for this error class.

These fields are additive and optional: they are populated only for the catalogued error classes (the highest-traffic codes). A code not yet in the catalog simply omits them — there is no retryable-by-default, so their absence never implies "safe to retry". Existing consumers that read only error_code / explanation are unaffected.

Note the language contract: fix_hint is machine-facing and therefore English by default, so fix_hint and fix_hint_en carry the same English text today. This differs from the summary / summary_en pair, where summary is Norwegian bokmål and summary_en is its translation.

A transient upstream failure, for example, tells an agent to back off and retry the identical call:

{
  "success": false,
  "error_code": "UPSTREAM_UNAVAILABLE",
  "explanation": {
    "summary": "Kilden er midlertidig utilgjengelig.",
    "summary_en": "The upstream source is temporarily unavailable."
  },
  "retryable": true,
  "fix_hint": "The upstream service is unavailable or timed out — retry the identical call after a short backoff (seconds).",
  "fix_hint_en": "The upstream service is unavailable or timed out — retry the identical call after a short backoff (seconds).",
  "docs_url": "https://www.apier.no/docs/guides/error-handling",
  "_meta": {
    "rulebook_version": "2026.6.0"
  }
}

A validation failure, by contrast, carries retryable: false — resending the same body fails identically, so the agent must correct the field named in explanation.details first.

error_code catalogue

Two source files back this catalogue, and they answer different questions:

  • EXPLAINER_ERROR_CODES (src/types/explainer.ts) — 40 codes that carry a full enriched explanation (summary, why, fix steps, handover), produced by the Compliance Explainer in src/lib/compliance/explainer.ts. This is the authoritative list for explanation coverage; a code outside it degrades to UNKNOWN in the explainer.
  • ERROR_CATALOG (src/lib/api/error-catalog.ts) — 28 codes that additionally carry the top-level machine-actionable attributes described above (retryable, fix_hint / fix_hint_en, docs_url). This is the authoritative list for machine-actionable coverage.

The two sets overlap but neither contains the other, and a code can legitimately appear in one only. Every code from both is listed below, grouped by theme.

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.
AUTH_MISSINGNo API key was presented in the Authorization: Bearer header.
AUTH_INVALID_KEYThe presented API key was rejected — unknown, malformed, or revoked (the three are deliberately indistinguishable).
AUTH_CONSUMER_INACTIVEThe key is valid but its consumer account is inactive; a human must reactivate it before the key works.
FULLMAKT_PACKAGE_NOT_GRANTEDThe acting delegation provably lacks an Altinn access package (tilgangspakke) the action requires.

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.
ORG_NUMBER_INVALID_CHECKSUMThe nine digits are well-formed but fail the MOD-11 checksum, so no such organisation number can exist.
DEADLINE_PASSEDThe filing deadline had already passed at call time.
REQUEST_TOO_LARGEThe request body exceeds the 256 KB limit for write calls.
INVALID_CURRENCYThe currency is not an ISO-4217 code Norges Bank publishes a series for.
NO_RATE_AVAILABLENorges Bank publishes no exchange rate for that currency and date combination.

Scope & plan

CodeMeaning
SCOPE_MISSINGThe required Maskinporten scope is not in the consumer's grant.
SCOPE_INSUFFICIENTThe API key does not hold the scope this endpoint requires — use a key that does.
SCOPE_INSUFFICIENT_FOR_ACTIONThe active delegation does not cover every Maskinporten scope the action type requires (see missing_scopes).
SCOPE_RESERVEDThe endpoint requires a reserved scope (write: / act: / delegate:) that is not issuable yet — the surface is human-gated.
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_INVALID_FORMATThe Idempotency-Key header is present but is not an RFC-4122 UUID.
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.

Billing & credits

Money and account-ceiling errors an autonomous agent has to survive without a human in the loop. HTTP status is stated because the recovery branch usually keys on it. The full recovery walkthrough — price discovery, the 402 contract, agent-initiated top-ups — is in Agent payments. The write-limiter's RATE_LIMITED 429, which also guards the top-up and key routes, is listed under Rate limiting with its sibling.

CodeMeaning
INSUFFICIENT_CREDITS402 — the prepaid balance cannot cover this call. Nothing was charged. Top up (see the top_up_url field on the body), then retry.
CREDIT_CHECK_UNAVAILABLE503 — the balance could not be read, so the call was refused fail-closed. Nothing was charged; retry after a short backoff.
TOPUP_BELOW_MINIMUM400 — the requested amount_ore is under the minimum top-up. The body names the minimum; raise amount_ore and resend.
TOPUP_CEILING_EXCEEDED400 — the requested amount_ore is above the ceiling for agent-initiated top-ups. Lower it to the ceiling named on the body, or ask a human to top up without a ceiling from the billing dashboard.
MAX_KEYS_REACHED409 — the account already holds the maximum of three active API keys. Revoke an unused key first.
ISSUANCE_TOKEN_INVALID401 — the one-time key-issuance token cannot be redeemed (expired, already used, revoked, or unknown — deliberately indistinguishable). Ask the account owner to mint a fresh one.
BILLING_NOT_CONFIGURED503 — billing is not configured in this environment. Operator-side; nothing was charged. Emitted by the browser-facing billing routes rather than the agent /api/v1 surface.

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.
ALTINN_ACK_UNPARSEABLEAltinn acknowledged the write with a 2xx but the receipt body could not be parsed — never retry; this needs manual reconciliation.
BRREG_DOWNBrønnøysund is temporarily unavailable — retry the identical call after a short backoff.
COMPANY_LOOKUP_FAILEDThe company lookup failed transiently on the way to the register — retry after a short backoff.

Rate limiting

Two distinct limiters, two distinct codes. Both carry a Retry-After header; wait it out rather than retrying immediately.

CodeMeaning
RATE_LIMIT_EXCEEDEDThe API key hit its per-minute rate limit for this route and tier. Your current per-minute and per-day ceilings are readable at GET /api/v1/account/usage.
RATE_LIMITED429 — the per-hour write limiter on the self-service account and billing routes (key creation and revocation, issuance tokens, top-up requests, webhook subscriptions).

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.
SERVER_ERRORA transient server-side fault — retry once after a short backoff, and report the correlation id if it persists.
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://www.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."
      ],
      "summary_en": "No active system-user delegation exists for 999999999.",
      "why_en": "The consumer has no active system-user delegation in Altinn for 999999999.",
      "fix_steps_en": [
        "Create a system user via altinn.no/systembruker and connect it to the integration.",
        "Ask a person with signing authority to approve the delegation in Altinn.",
        "Retry the request once the delegation shows as active."
      ],
      "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 both the Norwegian and English text wherever the template references them; omit them and the explanation falls back to a neutral noun in each language. 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.

Building with an LLM? Read llms.txt for agent-oriented integration guidance.