Skip to content
Apier
Apier.no
Guides

Error handling and the Compliance Explainer

Structured error codes, Norwegian-language fix steps, and the human-agent handover boundary.

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

Every Apier error response carries a structured envelope so your agent can handle failures programmatically — no string-matching required.

Error envelope

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

{
  "success": false,
  "error_code": "AUTH_NO_DELEGATION",
  "explanation": {
    "summary": "Organisasjonen har ikke delegert tilgang til Apier.",
    "why": "Regelmotoren trenger en delegert systembruker for å lese Tier 2-data.",
    "fix_steps": [
      "Opprett en systembruker i Altinn",
      "Deleger tilgang til Apier"
    ],
    "relevant_link": "https://altinn.no",
    "legal_basis": null,
    "handover": {
      "who": "altinn_user",
      "where": "https://altinn.no",
      "what": "Deleger systembrukertilgang til Apier.",
      "why": "Agenten kan ikke opprette delegeringen selv."
    }
  },
  "_meta": {
    "rulebook_version": "1.0.0",
    "data_freshness": "2026-05-25T08:00:00Z"
  }
}

The _meta block rides on errors too — so your agent can diff the rulebook version it last saw against the version that just failed.

The explanation object

explanation carries a required summary plus optional why, fix_steps, relevant_link, legal_basis, and handover. All human-facing text is Norwegian bokmål. The type lives in src/types/explainer.ts (Explanation).

Error codes

The Compliance Explainer enriches a catalogue of structured codes — the authoritative list is the EXPLAINER_ERROR_CODES tuple in src/types/explainer.ts. A representative sample:

CodeMeaning
VALIDATION_FAILEDRequest failed Zod validation at the boundary — fix the input
COMPANY_NOT_FOUNDOrganisation number not found in Brønnøysund
AUTH_NO_DELEGATIONNo Altinn delegation — escalate to request one
SCOPE_MISSINGAPI key lacks the scope this endpoint requires
RATE_LIMIT_EXCEEDEDTier rate limit hit — back off and retry
UPSTREAM_UNAVAILABLEGovernment API unreachable — wait and retry
IDEMPOTENCY_KEY_REQUIREDA write needs an Idempotency-Key header
APPROVAL_TOKEN_REQUIREDA submission needs a human-approved token
DEADLINE_PASSEDThe obligation deadline is in the past
EXECUTION_CIRCUIT_OPENUpstream circuit breaker is open — retry later
INTERNAL_ERRORApier internal error — contact support@apier.no

The catalogue is append-only (Rule 10): new codes are added, existing ones never change meaning. A code the explainer does not recognise degrades to UNKNOWN rather than leaking an internal message.

The handover pointer

explanation.handover is either null (the agent can resolve the error itself — retry, adjust input, or wait) or a HandoverAction object telling the agent to stop and escalate to a human:

{ "who": "altinn_user", "where": "…", "what": "…", "why": "…" }

who is one of company_admin, accountant, altinn_user, or apier_support (the closed HandoverActor union). where, what, and why give the agent everything it needs to compose a hand-off message. Upstream outages are deliberately not a handover case — they resolve by waiting, so UPSTREAM_UNAVAILABLE ships handover: null.

The Compliance Explainer endpoint

POST /api/v1/explain takes a body of { error_code, context? } — where error_code is one of the catalogue codes — and returns the full Norwegian-language Explanation (summary, why, fix steps, handover). It is a zero-auth Category A endpoint, so you can surface human-readable guidance in your agent's UI without spending an API key.

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