Hopp til innhold

Apier.no

Oppskrifter

Menneskelesbare gjennomganger av de kanoniske agent-arbeidsflytene. Hver oppskrift speiler nøyaktig én oppføring i /workflows.json — det maskinlesbare manifestet crawlere og agent-rammeverk konsumerer. For hele evne-listen, se /api/v1/capabilities.

Jobb-formede oppskrifter

Oppgave-først gjennomganger for de fire live-kombinasjonene — jobb- og «for plattformer»-oppskrifter per kombinasjon, pluss en sammensatt KYB-onboarding-kjede.

Look up Norwegian business deadlines for a year

workflow.lookup-deadlines · Slå opp norske forretningsfrister for et år

Fetch the canonical deadline list (MVA terminer, A-melding, skattemelding, årsregnskap, Foretaksregisteret årsbekreftelse) for a calendar year. Deadlines are pre-adjusted through weekends and Norwegian public holidays, with the original legal deadline surfaced in `adjusted_from` when relevant.

Intensjon
Find all upcoming Norwegian business deadlines for a given calendar year.
Forventet resultat
An ordered list of deadline entries sorted ascending by date, each with obligation_id, legal deadline, adjusted deadline (when pushed for weekends/holidays), and legal reference.
Utløsende intensjon
What Norwegian business deadlines are coming up in YYYY?
Estimert tid
~200 ms · ingen autentisering

Steg

  1. 1

    Call GET /api/v1/public/deadlines?year=YYYY and iterate the returned mappings sorted ascending by deadline.

    public.deadlinesJSON envelope with data.year, data.deadlines[] (sorted ascending), and _meta.served_from='static'.

Agent-instruksjoner

1. Call GET /api/v1/public/deadlines?year=<YYYY> (no authentication required).
2. Parse the response body at data.deadlines — it is sorted ascending by deadline.
3. For each entry, note obligation_id, deadline (ISO 8601 with Europe/Oslo offset), and adjusted_from (null unless the legal deadline fell on a weekend or holiday).
4. If data.deadlines is empty, the year is valid but outside our coverage window (2020-2100) — surface VALIDATION_FAILED explanation to the user.

Feilmoduser å planlegge for

  • invalid_year
  • upstream_timeout

Eksempelforespørsel

GET /api/v1/public/deadlines?year=2026

Check a Norwegian company's current Brønnøysund status

workflow.check-company-status · Sjekk en norsk virksomhets gjeldende Brønnøysund-status

Fetch the current Tier 1 + (when delegation exists) Tier 2 view of a Norwegian company by org number. `data.data_tier` tells you whether Tier 2 was served; `_meta.served_from` distinguishes cache from live.

Intensjon
Retrieve the current Brønnøysund-sourced status and registry metadata for a Norwegian company, including Tier 2 commercial metrics when a delegation is in place.
Forventet resultat
Company context object with name, entity_type, NACE codes, status (active/deregistered/dissolved), municipality, signaturrett/prokura — plus Tier 2 fields (employee_count, annual_turnover, total_assets) when the caller has an active delegation.
Utløsende intensjon
Is company with org_number 999999999 still active, and what is its current name?
Estimert tid
~500 ms · krever API-nøkkel (free+)

Steg

  1. 1

    Call GET /api/v1/company/{org}/context with the consumer API key; branch on data.data_tier.

    company.contextJSON envelope with data.company (tier-1 fields), optional data.tier_2 block, data.data_tier, and _meta with served_from + stale markers.

Agent-instruksjoner

1. Ensure you hold a consumer API key in the Authorization: Bearer header.
2. Call GET /api/v1/company/<ORG_NUMBER>/context with ORG_NUMBER as a 9-digit Norwegian organisation number.
3. Branch on data.data_tier — 'tier_1' means public-only Brønnøysund fields; 'tier_2' means the delegation is active and commercial metrics are included.
4. Read _meta.served_from ('cache' vs 'live') and _meta.stale (true when a within-limit cached row was served as an upstream-down fallback).
5. On 404 org_not_found: surface the explanation.why text (Norwegian) to the user.
6. On 503 with _meta.stale=true: the data is still usable but older than 24 hours — tell the user freshness is degraded.

Feilmoduser å planlegge for

  • org_not_found
  • tier2_data_missing
  • upstream_timeout
  • auth_missing
  • auth_invalid_key

Eksempelforespørsel

curl -H 'Authorization: Bearer <API_KEY>' https://www.apier.no/api/v1/company/999999999/context

Look up the official NOK exchange rate for a date

workflow.exchange-rate-lookup · Slå opp offisiell NOK-kurs for en dato

Fetch the Norges Bank NOK rate for a currency and date. Weekend/holiday/pre-publication-today requests fall back to the most recent prior business day; `data.date` is the actual publication date and `data.requested_date` is what was asked for.

Intensjon
Fetch the official Norges Bank NOK exchange rate for a currency and optional date, with automatic fallback to the most recent prior business day when the requested date is a weekend, holiday, or before today's ~16:00 Oslo publication.
Forventet resultat
A rate object: base='NOK', quote=<uppercased ISO>, rate (1 quote = rate NOK), date (actual publication date), requested_date (what you asked for), source='Norges Bank'.
Utløsende intensjon
What was the EUR/NOK rate on 2026-04-10?
Estimert tid
~300 ms · ingen autentisering

Steg

  1. 1

    Call GET /api/v1/tools/exchange-rate?currency=<ISO>&date=<YYYY-MM-DD>.

    tools.exchange_rateJSON envelope with data.rate (number), data.date, data.requested_date, data.cached, and _meta.served_from (cache/live).

Agent-instruksjoner

1. Call GET /api/v1/tools/exchange-rate?currency=<ISO>&date=<YYYY-MM-DD> (no authentication).
2. CURRENCY must be a 3-letter ISO 4217 code Norges Bank tracks (EUR, USD, GBP, SEK, DKK, etc.).
3. DATE is optional — omit to get today-in-Oslo; future dates are rejected with 400 INVALID_DATE.
4. Compare data.date to data.requested_date. If they differ, the requested date fell on a weekend / holiday / pre-publication window and the rate is from the most recent prior business day.
5. On 404 NO_RATE_AVAILABLE: Norges Bank does not track this currency — try EUR or USD as a fallback.
6. On 502 UPSTREAM_UNAVAILABLE: transient; retry in a few minutes.

Feilmoduser å planlegge for

  • invalid_currency
  • invalid_date
  • no_rate_available
  • upstream_unavailable

Eksempelforespørsel

GET /api/v1/tools/exchange-rate?currency=EUR&date=2026-04-10

Translate an Altinn 2 code to the Altinn 3 equivalent

workflow.altinn-role-migration · Oversett en Altinn 2-kode til Altinn 3-motparten

Translate an Altinn 2 service or role code to its Altinn 3 equivalent. The 19 June 2026 Altinn 2 deprecation deadline has passed, so this identifies what a legacy code maps to for migration remediation. Gate production migration actions on `verified === true`; unverified entries are convenience references only.

Intensjon
Discover the Altinn 3 resource or role that replaces a given Altinn 2 service/role code, now that the 19 June 2026 Altinn 2 deprecation cliff has passed.
Forventet resultat
A migration entry with altinn2_code, altinn3_code (possibly null if DigDir hasn't published an equivalent yet), migration_notes in Norwegian and English, service_owner, and a `verified` flag indicating whether the mapping has been cross-checked against DigDir's authoritative source.
Utløsende intensjon
What Altinn 3 role corresponds to Altinn 2 code A0208?
Estimert tid
~150 ms · ingen autentisering

Steg

  1. 1

    Call GET /api/v1/tools/altinn-migration?altinn2_code=<CODE>; inspect `verified` before trusting the mapping for production automation.

    tools.altinn_migrationJSON envelope with data.entry (MigrationEntry), data.deprecation_deadline, data.days_remaining, data.deadline_passed, and _meta.served_from='static'.

Agent-instruksjoner

1. Call GET /api/v1/tools/altinn-migration?altinn2_code=<CODE> (no authentication). CODE is alphanumeric, max 10 characters (e.g. A0208).
2. Read data.entry.verified — if false, the mapping is a best-effort reference and MUST NOT drive production migration without human review.
3. Read data.entry.altinn3_code — null means DigDir has not yet published the Altinn 3 equivalent.
4. The 19 June 2026 Altinn 2 cliff has passed, so data.deadline_passed is true and data.days_remaining is 0 — tell the user the cutoff is already behind them rather than presenting a countdown.
5. On 404 NOT_FOUND: the code is not in our static map — point the user at docs.altinn.studio.

Feilmoduser å planlegge for

  • invalid_code
  • not_found
  • unverified_entry

Eksempelforespørsel

GET /api/v1/tools/altinn-migration?altinn2_code=A0208

List generic obligations for a Norwegian entity type

workflow.obligation-overview · List generelle forpliktelser for en norsk selskapsform

Fetch the universal obligation set for a given entity type (AS, ENK, ANS, DA, NUF). Template layer only — `tier_2_required: true` entries need commercial data to evaluate per-company, which requires an Altinn delegation.

Intensjon
List the universal regulatory obligations (tax, reporting, insurance, registration) that apply to a Norwegian entity type, and identify which of those need Tier 2 commercial data to evaluate per-company.
Forventet resultat
Obligation template set: each entry names the obligation, category, frequency, required/conditionally/never applicability, a Norwegian condition string, tier_2_required flag, and the Lovdata legal reference.
Utløsende intensjon
What obligations apply to a Norwegian aksjeselskap (AS)?
Estimert tid
~150 ms · ingen autentisering

Steg

  1. 1

    Call GET /api/v1/public/obligations?entity_type=<AS|ENK|ANS|DA|NUF>. Use the `tier_2_required` flag to decide whether to plan a delegation flow next.

    public.obligationsJSON envelope with data.entity_type, data.obligations[] (may be empty for ANS/DA/NUF), data.notes[], and _meta.served_from='static'.

Agent-instruksjoner

1. Call GET /api/v1/public/obligations?entity_type=<AS|ENK|ANS|DA|NUF> (no authentication).
2. Iterate data.obligations — an array of obligation templates.
3. For each obligation with tier_2_required === true, plan ahead: the caller will need an Altinn delegation (workflow.request-delegation, not yet shipped) before the paid /v1/company/{org}/obligations endpoint can evaluate it per-company.
4. Obligations with required='never' are DELIBERATELY included so agents see they were considered and ruled out (e.g. revisor-plikt for ENK).
5. ANS, DA, and NUF currently return an empty obligations array with a notes entry — templates are not yet published.

Feilmoduser å planlegge for

  • invalid_entity_type
  • empty_template_set

Eksempelforespørsel

GET /api/v1/public/obligations?entity_type=AS

Reconcile a customer's filing history from the audit trail

workflow.reconcile-filing-history · Avstem en kundes innsendingshistorikk fra sporingsloggen

Pull the consumer's own audit trail (Sporingslogg) for a single org_number across a date range, paging via the keyset cursor (next_before + next_before_id) until exhausted. Useful for accounting firms reconciling activity after the fact, AI-agent operators debugging filing flows, and producing a forensic timeline for dispute defense. Returns ONLY rows YOUR consumer wrote — cross-consumer visibility is structurally impossible.

Intensjon
Reconstruct the activity timeline a single consumer's API key generated against one Norwegian organisation, optionally narrowed by action type or initiator class, for reconciliation, debugging, or dispute defense.
Forventet resultat
Ordered (timestamp DESC, id DESC) page of AuditLogEntry rows the consumer wrote for the org, each carrying correlation_id (joins to provenance_log / evaluation_snapshots / compliance_state_events), initiated_by classification, schema_version, and a scrubbed details JSONB.
Utløsende intensjon
Show me every audit-log row my consumer wrote for org 999999999 in the last 90 days.
Estimert tid
~250 ms · krever API-nøkkel (free+)

Steg

  1. 1

    Call GET /api/v1/company/{org}/audit with the consumer API key (read:audit scope). Iterate the page; if pagination.has_more, repeat with ?before=pagination.next_before&before_id=pagination.next_before_id.

    company.auditJSON envelope with data.data[] (AuditLogEntry array), data.pagination.has_more, data.pagination.next_before (string or absent), data.pagination.next_before_id (string or absent), and _meta with response_timestamp + response_hash.

Agent-instruksjoner

1. Ensure your API key has the read:audit scope (operator-issued via /v1/admin/keys).
2. Call GET /api/v1/company/<ORG_NUMBER>/audit?since=<ISO_FROM>&until=<ISO_TO>&limit=200 with the consumer API key.
3. Iterate data.data — each row is an AuditLogEntry. correlation_id joins to provenance_log / evaluation_snapshots / compliance_state_events from the same originating request.
4. If pagination.has_more is true, pass pagination.next_before back as ?before=<value> AND pagination.next_before_id back as ?before_id=<value> to fetch the next page. Both are required together — the cursor is a tuple, not two independent fields.
5. To narrow further: ?action=<closed-enum> or ?initiated_by=<human|agent|cron|system|unknown>. Action enum is the closed list at src/lib/audit/types.ts AUDIT_ACTIONS — anything outside the list is rejected at 400.
6. details.* values matching token / secret / password / bearer / authorization / jwt / api_key / private_key / credential / client_secret / refresh_token are auto-redacted to the literal string [REDACTED] at BOTH write and read time.
7. An empty array (data.data === []) for a valid (consumer, org) pair is returned as 200, not 404 — that prevents existence-leak across consumers.

Feilmoduser å planlegge for

  • auth_missing
  • scope_insufficient
  • validation_failed
  • audit_query_failed

Eksempelforespørsel

curl -H 'Authorization: Bearer <API_KEY>' 'https://www.apier.no/api/v1/company/999999999/audit?limit=50&initiated_by=agent'

Track historical changes for a customer company

workflow.track-changes · Følg historiske endringer for en kunde-virksomhet

Pull all change events for a specific org_number from the change archive (Brreg ingestion + Altinn / DigDir / Norges Bank multi-source). Cursor-paginated; pass next_cursor back as ?cursor= for the next page.

Intensjon
Subscribe (via polling) to changes affecting a Norwegian company, audit historical mutations, or reconstruct what Apier saw at a given time across all four upstream sources.
Forventet resultat
Page of change events (created/updated/deleted) ordered detected_at DESC, id DESC. Each row carries source_snapshot_id for joining to the response receipt, plus a derived observation_kind (first_observation = the archive's first sighting, value_change = a real observed transition). With entity_id supplied (this workflow's golden path) personal role-holder fields are included; without it, role-holder field rows AND whole-entity company created/deleted rows (their snapshots embed role-holder arrays) are withheld — intentionally, not as missing archive data — and personal_fields_withheld is true.
Utløsende intensjon
Show me everything that changed for org_number 998877665 in the last 30 days.
Estimert tid
~200 ms · krever API-nøkkel (starter+)

Steg

  1. 1

    Call GET /api/v1/changes?source=brreg&entity_id={org_number}&from={iso_date} with the consumer API key (read:changes scope). Iterate the page; if pagination.has_more, repeat with ?cursor=pagination.next_cursor.

    changes.queryJSON envelope with data.data[] (PublicChangeRow array), data.pagination.has_more, data.pagination.next_cursor (string or null), and _meta with response_timestamp + response_hash.

Agent-instruksjoner

1. Ensure your API key has the read:changes scope (operator-issued via /v1/admin/keys).
2. Call GET /api/v1/changes with filters: source (brreg|altinn|digdir|norges_bank|nav|skatteetaten), entity_id, change_type (created|updated|deleted), from + to (RFC 3339).
3. Iterate data.data — each row is a created/updated/deleted event with before_value/after_value JSONB blobs, an RFC 6902 diff array, and a derived observation_kind (treat first_observation rows as the archive's first sighting of that field/entity, not a real-world change).
4. If pagination.has_more is true, pass pagination.next_cursor back as ?cursor=<value> to fetch the next page. Do NOT modify the cursor — it's HMAC-signed and tampered cursors return 400 CURSOR_INVALID.
5. correlation_id is intentionally not exposed; use source_snapshot_id to join back to provenance receipts.

Feilmoduser å planlegge for

  • auth_missing
  • scope_insufficient
  • cursor_invalid
  • validation_failed

Eksempelforespørsel

curl -H 'Authorization: Bearer <API_KEY>' 'https://www.apier.no/api/v1/changes?source=brreg&entity_id=998877665&from=2026-01-01T00:00:00Z'

Validate a filing before submission

workflow.validate-filing · Valider en innlevering før innsending

Run the five preflight checks the dry-run engine performs against a filing payload — company exists, system user authorised, scopes delegated, payload format valid, deadline in future — without submitting anything to Altinn / Skatteetaten / NAV. Use this before any human-approval flow so the agent can present a complete pass/fail picture rather than discovering problems mid-flight.

Intensjon
Pre-flight a regulatory filing payload to discover every problem in one call, BEFORE the live submission burns an idempotency key or surfaces a partial commit at the upstream.
Forventet resultat
DryRunOutcome with all_passed (boolean) and checks[5] (per-check pass/fail with structured error_code on failures). The disclaimer field reminds the agent that a passing dry-run is NOT a guarantee of submission success.
Utløsende intensjon
Will my MVA-melding for 2026-T2 pass before I submit it?
Estimert tid
~600 ms · krever API-nøkkel (starter+)

Steg

  1. 1

    Call POST /api/v1/actions/execute?dry_run=true with { org_number, action_type, period, payload }. The endpoint performs all five preflight checks, writes one evaluation_snapshots row + one audit_log row, and returns 200 with the structured DryRunOutcome.

    actions.execute_dry_runJSON envelope with data.dry_run === true, data.outcome.all_passed (boolean), data.outcome.checks (5 entries, ordered), data.outcome.disclaimer (fixed string), and _meta with response_timestamp + response_hash.

Agent-instruksjoner

1. Ensure your API key has the read:actions scope (operator-issued via /v1/admin/keys).
2. Build the request body: { org_number (9 digits), action_type ("mva_melding" | "a_melding"), period (YYYY-Tn|YYYY-A|YYYY-MM for mva; YYYY-MM for a-melding), payload (per-action shape — see OpenAPI components MvaMeldingPayload / AMeldingPayload). Decimals as STRINGS, not numbers.
3. POST /api/v1/actions/execute?dry_run=true with the body. Note ?dry_run=true is what makes this call validate-only — omitting it (or sending any value other than "true") routes to the live-execute path for supported action types instead of a no-op (still mock-routed by default when ALTINN_MODE=mock, not necessarily a real government submission); see /docs/capability-status for the current live/gated status of each action type before relying on that path.
4. Read response data.outcome.all_passed. If true, the dry-run found no blockers; live submission uses the live-execute flow (Idempotency-Key + approval token) and is enabled per-operator once Maskinporten/Altinn grants are active.
5. If false, iterate data.outcome.checks: each row has check (name), passed (bool), error_code (string|null), explanation_summary (string|null). Fix the inputs against the failed checks and retry — the engine never short-circuits, so one call lists every problem.
6. Treat the disclaimer field as a hard contract: a passing dry-run is NOT a guarantee. Government systems may reject otherwise-valid submissions for reasons outside Apier's view.

Feilmoduser å planlegge for

  • auth_missing
  • scope_insufficient
  • validation_failed
  • execute_not_available
  • payload_too_large

Eksempelforespørsel

Dry-run: POST /api/v1/actions/execute?dry_run=true with headers { Authorization: Bearer <KEY> } and body { org_number, action_type, period, payload }. Live-execute: POST /api/v1/actions/execute with headers { Authorization: Bearer <KEY>, Idempotency-Key: <UUID>, X-Approval-Token: <token> } and body { org_number, action_type: "mva_melding", period, payload }. Both modes require API-key auth via Authorization header (round 5 manifest fix — was previously omitted from the dry-run half).

Onboard a Norwegian client company from a single org number (KYB)

workflow.kyb-client-onboarding · Onboard en norsk kundevirksomhet fra ett organisasjonsnummer (KYB)

Composed five-step KYB (know-your-business) onboarding chain over the live company reads: verify the company exists and is safe to act for, resolve who can legally sign for it, read its filed annual accounts, evaluate its regulatory obligations, and expand its concrete deadline calendar. Every step's response carries `_meta.response_hash` and lands a provenance_log row, so the assembled onboarding answer is provenance-backed end-to-end; the verify and authority steps optionally return an offline-verifiable detached-JWS certificate via `?certificate=true`.

Intensjon
Onboard a Norwegian client company from a single organisation number: establish that it is real and active, who holds acting capacity, what its filed accounts show, which obligations apply, and when they fall due — one provenance-stamped answer per question.
Forventet resultat
A provenance-backed onboarding summary assembled from five responses: a pass/warn/fail verification verdict, a signing-authority classification with the named holders, the filed annual-accounts snapshot with key figures, the evaluated obligation catalogue, and the weekend/holiday-adjusted deadline calendar — each response carrying `_meta.response_hash` (joinable to provenance_log), with optional detached-JWS certificates from the verify and authority steps for offline re-verification.
Utløsende intensjon
Onboard company 999999999 as a client — does it exist, who can sign for it, and what does it owe when?
Estimert tid
~2500 ms · krever API-nøkkel (free+)

Steg

  1. 1

    Call GET /api/v1/company/{org}/verify (optionally ?certificate=true) and gate the rest of the chain on data.verification_status — stop on 'fail'.

    company.verifyJSON envelope with data.verification_status (pass/warn/fail/unknown), data.signals (seven tri-state booleans), and _meta with response_hash; with ?certificate=true the data block is a detached-JWS certificate wrapping the same verdict.

  2. 2

    Call GET /api/v1/company/{org}/authority (optionally ?certificate=true) to resolve who can legally commit the company before any binding onboarding step.

    company.authorityJSON envelope with data.classification (sole/joint/by_role/prokura_only/no_authority/unknown), data.signaturrett_holders, data.prokura_holders, and _meta with response_hash.

  3. 3

    Call GET /api/v1/company/{org}/accounts for the filed annual-accounts snapshot — treat has_filed_annual_accounts null as unknown, never as 'not filed'.

    company.accountsJSON envelope with data.has_filed_annual_accounts (tri-state), data.last_accounts_year, data.key_figures (with explicit currency), and _meta with response_hash.

  4. 4

    Call GET /api/v1/company/{org}/obligations to evaluate every Rulebook obligation for the company — insufficient_data verdicts point at the Tier-2 delegation path.

    company.obligationsJSON envelope with data.obligations[] (one EvaluationResult per rule: applicable/not_applicable/insufficient_data), data.data_tier, and _meta with response_hash.

  5. 5

    Call GET /api/v1/company/{org}/deadlines to expand the applicable obligations into the concrete weekend/holiday-adjusted deadline calendar.

    company.deadlinesJSON envelope with data.deadlines[] (DeadlineEntry rows, due_at ascending, Europe/Oslo offsets), data.data_tier, and _meta with response_hash.

Agent-instruksjoner

1. Ensure you hold a consumer API key (Authorization: Bearer) with the read:brreg scope; ORG_NUMBER below is a 9-digit Norwegian organisation number.
2. Call GET /api/v1/company/<ORG_NUMBER>/verify. Branch on data.verification_status: 'fail' means the company is not active — stop onboarding and surface data.summary; 'warn' means active but no signing authority is defined — continue, but flag it; 'pass' continues. Append ?certificate=true when you want the verdict wrapped in an offline-verifiable detached-JWS certificate.
3. Call GET /api/v1/company/<ORG_NUMBER>/authority. Read data.classification (sole / joint / by_role / prokura_only / no_authority / unknown) and data.signaturrett_holders + data.prokura_holders to know who must approve binding steps. ?certificate=true is available here too.
4. Call GET /api/v1/company/<ORG_NUMBER>/accounts. data.has_filed_annual_accounts is tri-state (true / false / null=unknown — never coerce null to false); data.key_figures carries the latest filed year's figures with an explicit currency.
5. Call GET /api/v1/company/<ORG_NUMBER>/obligations. Each EvaluationResult is applicable / not_applicable / insufficient_data — treat insufficient_data as 'needs a Tier-2 delegation', not as a no.
6. Call GET /api/v1/company/<ORG_NUMBER>/deadlines. Entries are already weekend/holiday-adjusted with Europe/Oslo offsets; sort order is due_at ascending.
7. Assemble the onboarding summary from the five data blocks. Keep each response's _meta.response_hash (and the step-2/3 certificates if requested) as the provenance trail for the decision.

Feilmoduser å planlegge for

  • org_not_found
  • auth_missing
  • auth_invalid_key
  • scope_insufficient
  • upstream_timeout

Eksempelforespørsel

curl -H 'Authorization: Bearer <API_KEY>' https://www.apier.no/api/v1/company/999999999/verify