{"version":"1","schema_version":"1.1.0","@context":"https://schema.org","@graph":[{"@type":"HowTo","@id":"https://www.apier.no/workflows.json#workflow.lookup-deadlines","name":"Look up Norwegian business deadlines for a year","description":"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.","totalTime":"PT1S","step":[{"@type":"HowToStep","position":1,"name":"Call GET /api/v1/public/deadlines?year=YYYY and iterate the returned mappings sorted ascending by deadline.","text":"JSON envelope with data.year, data.deadlines[] (sorted ascending), and _meta.served_from='static'."}]},{"@type":"HowTo","@id":"https://www.apier.no/workflows.json#workflow.check-company-status","name":"Check a Norwegian company's current Brønnøysund status","description":"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.","totalTime":"PT1S","step":[{"@type":"HowToStep","position":1,"name":"Call GET /api/v1/company/{org}/context with the consumer API key; branch on data.data_tier.","text":"JSON envelope with data.company (tier-1 fields), optional data.tier_2 block, data.data_tier, and _meta with served_from + stale markers."}]},{"@type":"HowTo","@id":"https://www.apier.no/workflows.json#workflow.exchange-rate-lookup","name":"Look up the official NOK exchange rate for a date","description":"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.","totalTime":"PT1S","step":[{"@type":"HowToStep","position":1,"name":"Call GET /api/v1/tools/exchange-rate?currency=<ISO>&date=<YYYY-MM-DD>.","text":"JSON envelope with data.rate (number), data.date, data.requested_date, data.cached, and _meta.served_from (cache/live)."}]},{"@type":"HowTo","@id":"https://www.apier.no/workflows.json#workflow.altinn-role-migration","name":"Translate an Altinn 2 code to the Altinn 3 equivalent","description":"Before the 19 June 2026 deprecation deadline, translate an Altinn 2 service or role code to the Altinn 3 equivalent. Gate production migration actions on `verified === true`; unverified entries are convenience references only.","totalTime":"PT1S","step":[{"@type":"HowToStep","position":1,"name":"Call GET /api/v1/tools/altinn-migration?altinn2_code=<CODE>; inspect `verified` before trusting the mapping for production automation.","text":"JSON envelope with data.entry (MigrationEntry), data.deprecation_deadline, data.days_remaining, data.deadline_passed, and _meta.served_from='static'."}]},{"@type":"HowTo","@id":"https://www.apier.no/workflows.json#workflow.obligation-overview","name":"List generic obligations for a Norwegian entity type","description":"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.","totalTime":"PT1S","step":[{"@type":"HowToStep","position":1,"name":"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.","text":"JSON envelope with data.entity_type, data.obligations[] (may be empty for ANS/DA/NUF), data.notes[], and _meta.served_from='static'."}]},{"@type":"HowTo","@id":"https://www.apier.no/workflows.json#workflow.reconcile-filing-history","name":"Reconcile a customer's filing history from the audit trail","description":"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.","totalTime":"PT1S","step":[{"@type":"HowToStep","position":1,"name":"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.","text":"JSON 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."}]},{"@type":"HowTo","@id":"https://www.apier.no/workflows.json#workflow.track-changes","name":"Track historical changes for a customer company","description":"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.","totalTime":"PT1S","step":[{"@type":"HowToStep","position":1,"name":"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.","text":"JSON envelope with data.data[] (PublicChangeRow array), data.pagination.has_more, data.pagination.next_cursor (string or null), and _meta with response_timestamp + response_hash."}]},{"@type":"HowTo","@id":"https://www.apier.no/workflows.json#workflow.validate-filing","name":"Validate a filing before submission","description":"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.","totalTime":"PT1S","step":[{"@type":"HowToStep","position":1,"name":"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.","text":"JSON 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."}]}],"workflows":[{"id":"workflow.lookup-deadlines","name_en":"Look up Norwegian business deadlines for a year","name_nb":"Slå opp norske forretningsfrister for et år","description_en":"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.","trigger_intent_en":"What Norwegian business deadlines are coming up in YYYY?","intent":"Find all upcoming Norwegian business deadlines for a given calendar year.","expected_outcome":"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.","failure_modes":["invalid_year","upstream_timeout"],"estimated_time_ms":200,"agent_instructions":"1. Call GET /api/v1/public/deadlines?year=<YYYY> (no authentication required).\n2. Parse the response body at data.deadlines — it is sorted ascending by deadline.\n3. 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).\n4. If data.deadlines is empty, the year is valid but outside our coverage window (2020-2100) — surface VALIDATION_FAILED explanation to the user.","steps":[{"step":1,"capability_id":"public.deadlines","purpose":"Call GET /api/v1/public/deadlines?year=YYYY and iterate the returned mappings sorted ascending by deadline.","expected_response":"JSON envelope with data.year, data.deadlines[] (sorted ascending), and _meta.served_from='static'."}],"requires_auth":false,"tier_minimum":null},{"id":"workflow.check-company-status","name_en":"Check a Norwegian company's current Brønnøysund status","name_nb":"Sjekk en norsk virksomhets gjeldende Brønnøysund-status","description_en":"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.","trigger_intent_en":"Is company with org_number 123456789 still active, and what is its current name?","intent":"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.","expected_outcome":"Company context object with name, entity_type, NACE codes, status (active/deregistered/dissolved), municipality, signaturrett/prokura — plus Tier 2 fields (employee_count, annual_turnover, MVA status) when the caller has an active delegation.","failure_modes":["org_not_found","tier2_data_missing","upstream_timeout","auth_missing","auth_invalid_key"],"estimated_time_ms":500,"agent_instructions":"1. Ensure you hold a consumer API key in the Authorization: Bearer header.\n2. Call GET /api/v1/company/<ORG_NUMBER>/context with ORG_NUMBER as a 9-digit Norwegian organisation number.\n3. 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.\n4. Read _meta.served_from ('cache' vs 'live') and _meta.stale (true when a within-limit cached row was served as an upstream-down fallback).\n5. On 404 org_not_found: surface the explanation.why text (Norwegian) to the user.\n6. On 503 with _meta.stale=true: the data is still usable but older than 24 hours — tell the user freshness is degraded.","steps":[{"step":1,"capability_id":"company.context","purpose":"Call GET /api/v1/company/{org}/context with the consumer API key; branch on data.data_tier.","expected_response":"JSON envelope with data.company (tier-1 fields), optional data.tier_2 block, data.data_tier, and _meta with served_from + stale markers."}],"requires_auth":true,"tier_minimum":"free"},{"id":"workflow.exchange-rate-lookup","name_en":"Look up the official NOK exchange rate for a date","name_nb":"Slå opp offisiell NOK-kurs for en dato","description_en":"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.","trigger_intent_en":"What was the EUR/NOK rate on 2026-04-10?","intent":"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.","expected_outcome":"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'.","failure_modes":["invalid_currency","invalid_date","no_rate_available","upstream_unavailable"],"estimated_time_ms":300,"agent_instructions":"1. Call GET /api/v1/tools/exchange-rate?currency=<ISO>&date=<YYYY-MM-DD> (no authentication).\n2. CURRENCY must be a 3-letter ISO 4217 code Norges Bank tracks (EUR, USD, GBP, SEK, DKK, etc.).\n3. DATE is optional — omit to get today-in-Oslo; future dates are rejected with 400 INVALID_DATE.\n4. 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.\n5. On 404 NO_RATE_AVAILABLE: Norges Bank does not track this currency — try EUR or USD as a fallback.\n6. On 502 UPSTREAM_UNAVAILABLE: transient; retry in a few minutes.","steps":[{"step":1,"capability_id":"tools.exchange_rate","purpose":"Call GET /api/v1/tools/exchange-rate?currency=<ISO>&date=<YYYY-MM-DD>.","expected_response":"JSON envelope with data.rate (number), data.date, data.requested_date, data.cached, and _meta.served_from (cache/live)."}],"requires_auth":false,"tier_minimum":null},{"id":"workflow.altinn-role-migration","name_en":"Translate an Altinn 2 code to the Altinn 3 equivalent","name_nb":"Oversett en Altinn 2-kode til Altinn 3-motparten","description_en":"Before the 19 June 2026 deprecation deadline, translate an Altinn 2 service or role code to the Altinn 3 equivalent. Gate production migration actions on `verified === true`; unverified entries are convenience references only.","trigger_intent_en":"What Altinn 3 role corresponds to Altinn 2 code A0208?","intent":"Discover the Altinn 3 resource or role that replaces a given Altinn 2 service/role code, ahead of the 19 June 2026 deprecation cliff.","expected_outcome":"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.","failure_modes":["invalid_code","not_found","unverified_entry"],"estimated_time_ms":150,"agent_instructions":"1. Call GET /api/v1/tools/altinn-migration?altinn2_code=<CODE> (no authentication). CODE is alphanumeric, max 10 characters (e.g. A0208).\n2. Read data.entry.verified — if false, the mapping is a best-effort reference and MUST NOT drive production migration without human review.\n3. Read data.entry.altinn3_code — null means DigDir has not yet published the Altinn 3 equivalent.\n4. Surface data.days_remaining to the user so they know how long until the 19 June 2026 deprecation cliff.\n5. On 404 NOT_FOUND: the code is not in our static map — point the user at docs.altinn.studio.","steps":[{"step":1,"capability_id":"tools.altinn_migration","purpose":"Call GET /api/v1/tools/altinn-migration?altinn2_code=<CODE>; inspect `verified` before trusting the mapping for production automation.","expected_response":"JSON envelope with data.entry (MigrationEntry), data.deprecation_deadline, data.days_remaining, data.deadline_passed, and _meta.served_from='static'."}],"requires_auth":false,"tier_minimum":null},{"id":"workflow.obligation-overview","name_en":"List generic obligations for a Norwegian entity type","name_nb":"List generelle forpliktelser for en norsk selskapsform","description_en":"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.","trigger_intent_en":"What obligations apply to a Norwegian aksjeselskap (AS)?","intent":"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.","expected_outcome":"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.","failure_modes":["invalid_entity_type","empty_template_set"],"estimated_time_ms":150,"agent_instructions":"1. Call GET /api/v1/public/obligations?entity_type=<AS|ENK|ANS|DA|NUF> (no authentication).\n2. Iterate data.obligations — an array of obligation templates.\n3. 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.\n4. Obligations with required='never' are DELIBERATELY included so agents see they were considered and ruled out (e.g. revisor-plikt for ENK).\n5. ANS, DA, and NUF currently return an empty obligations array with a notes entry — templates are not yet published.","steps":[{"step":1,"capability_id":"public.obligations","purpose":"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.","expected_response":"JSON envelope with data.entity_type, data.obligations[] (may be empty for ANS/DA/NUF), data.notes[], and _meta.served_from='static'."}],"requires_auth":false,"tier_minimum":null},{"id":"workflow.reconcile-filing-history","name_en":"Reconcile a customer's filing history from the audit trail","name_nb":"Avstem en kundes innsendingshistorikk fra sporingsloggen","description_en":"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.","trigger_intent_en":"Show me every audit-log row my consumer wrote for org 123456789 in the last 90 days.","intent":"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.","expected_outcome":"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.","failure_modes":["auth_missing","scope_insufficient","validation_failed","audit_query_failed"],"estimated_time_ms":250,"agent_instructions":"1. Ensure your API key has the read:audit scope (operator-issued via /v1/admin/keys).\n2. Call GET /api/v1/company/<ORG_NUMBER>/audit?since=<ISO_FROM>&until=<ISO_TO>&limit=200 with the consumer API key.\n3. Iterate data.data — each row is an AuditLogEntry. correlation_id joins to provenance_log / evaluation_snapshots / compliance_state_events from the same originating request.\n4. 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.\n5. 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.\n6. 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.\n7. An empty array (data.data === []) for a valid (consumer, org) pair is returned as 200, not 404 — that prevents existence-leak across consumers.","steps":[{"step":1,"capability_id":"company.audit","purpose":"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.","expected_response":"JSON 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."}],"requires_auth":true,"tier_minimum":"free"},{"id":"workflow.track-changes","name_en":"Track historical changes for a customer company","name_nb":"Følg historiske endringer for en kunde-virksomhet","description_en":"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.","trigger_intent_en":"Show me everything that changed for org_number 998877665 in the last 30 days.","intent":"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.","expected_outcome":"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.","failure_modes":["auth_missing","scope_insufficient","cursor_invalid","validation_failed"],"estimated_time_ms":200,"agent_instructions":"1. Ensure your API key has the read:changes scope (operator-issued via /v1/admin/keys).\n2. Call GET /api/v1/changes with filters: source (brreg|altinn|digdir|norges_bank), entity_id, change_type (created|updated|deleted), from + to (RFC 3339).\n3. Iterate data.data — each row is a created/updated/deleted event with before_value/after_value JSONB blobs and an RFC 6902 diff array.\n4. 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.\n5. correlation_id is intentionally not exposed; use source_snapshot_id to join back to provenance receipts.","steps":[{"step":1,"capability_id":"changes.query","purpose":"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.","expected_response":"JSON envelope with data.data[] (PublicChangeRow array), data.pagination.has_more, data.pagination.next_cursor (string or null), and _meta with response_timestamp + response_hash."}],"requires_auth":true,"tier_minimum":"starter"},{"id":"workflow.validate-filing","name_en":"Validate a filing before submission","name_nb":"Valider en innlevering før innsending","description_en":"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.","trigger_intent_en":"Will my MVA-melding for 2026-T2 pass before I submit it?","intent":"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.","expected_outcome":"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.","failure_modes":["auth_missing","scope_insufficient","validation_failed","execute_not_available","payload_too_large"],"estimated_time_ms":600,"agent_instructions":"1. Ensure your API key has the read:actions scope (operator-issued via /v1/admin/keys).\n2. 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.\n3. POST /api/v1/actions/execute?dry_run=true with the body. Note the ?dry_run=true is REQUIRED at v1 — omitting it returns 501 EXECUTE_NOT_AVAILABLE.\n4. Read response data.outcome.all_passed. If true, the dry-run found no blockers; proceed to live submission once PR-077 lands.\n5. 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.\n6. 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.","steps":[{"step":1,"capability_id":"actions.execute_dry_run","purpose":"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.","expected_response":"JSON 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."}],"requires_auth":true,"tier_minimum":"starter"}],"sandbox":{"base_url":"https://www.apier.no/api/v1/sandbox","cors":"open","determinism":"byte-equivalent except _meta.response_timestamp","reserved_test_org_numbers":["999000001","999000002","999000003","999000004","999000005"],"endpoints":[{"capability_id":"company.context","url":"https://www.apier.no/api/v1/company/{org}/context","sandbox_url":"https://www.apier.no/api/v1/sandbox/company/{org}/context"},{"capability_id":"company.obligations","url":"https://www.apier.no/api/v1/company/{org}/obligations","sandbox_url":"https://www.apier.no/api/v1/sandbox/company/{org}/obligations"},{"capability_id":"company.deadlines","url":"https://www.apier.no/api/v1/company/{org}/deadlines","sandbox_url":"https://www.apier.no/api/v1/sandbox/company/{org}/deadlines"},{"capability_id":"company.summary","url":"https://www.apier.no/api/v1/company/{org}/summary","sandbox_url":"https://www.apier.no/api/v1/sandbox/company/{org}/summary"},{"capability_id":"company.audit","url":"https://www.apier.no/api/v1/company/{org}/audit","sandbox_url":"https://www.apier.no/api/v1/sandbox/company/{org}/audit"},{"capability_id":"auth.approval-token","url":"https://www.apier.no/api/v1/auth/approval-token","sandbox_url":"https://www.apier.no/api/v1/sandbox/auth/approval-token"},{"capability_id":"actions.execute","url":"https://www.apier.no/api/v1/actions/execute","sandbox_url":"https://www.apier.no/api/v1/sandbox/actions/execute"}]},"public_sandbox":{"base_url":"https://www.apier.no/api/v1/sandbox/public","cors":"open","determinism":"byte-equivalent except _meta.response_timestamp","fixture_org_number":"999999999","rate_limit_per_ip_per_hour":100,"auth":"none","provenance_log_emitted":false,"mcp_query_log_source_surface":"public_sandbox","copy_paste_examples_url":"https://www.apier.no/sandbox/examples","try_without_signup_workflow":[{"step":"context","method":"GET","url":"https://www.apier.no/api/v1/sandbox/public/company/999999999/context","body":null,"expected_status":200},{"step":"obligations","method":"GET","url":"https://www.apier.no/api/v1/sandbox/public/company/999999999/obligations","body":null,"expected_status":200},{"step":"summary","method":"GET","url":"https://www.apier.no/api/v1/sandbox/public/company/999999999/summary","body":null,"expected_status":200},{"step":"plan","method":"POST","url":"https://www.apier.no/api/v1/sandbox/public/actions/plan","body":{"org_number":"999999999","action":"mva_melding"},"expected_status":200}]},"_meta":{"data_freshness":"2026-04-28T00:00:00.000Z","source":"apier.no internal manifest","schema_version":"1.1.0","workflow_count":8}}