---
title: "Regulatory obligations evaluated for a specific company"
method: GET
path: "/api/v1/company/{org}/obligations"
tags: ["Company"]
---

# Regulatory obligations evaluated for a specific company

`GET /api/v1/company/{org}/obligations`

## Request

- Base URL: `https://www.apier.no`
- URL: `https://www.apier.no/api/v1/company/{org}/obligations`
- Auth: HTTP bearer

Returns every regulatory obligation the Universal Rulebook evaluates for a Norwegian organisation, one EvaluationResult entry per rule whose `entity_types[]` matches the company's entity_type. The response carries all three verdicts side-by-side so agents can see the full picture: `applicable` (every condition matched — the obligation applies), `not_applicable` (at least one condition failed — the obligation does not apply), and `insufficient_data` (a Tier 2 field the rule reads is null or the Tier 2 block is absent — the agent should surface a delegation path rather than decide yes/no). Do not filter server-side; agents filter client-side if they want a narrower view. `data_tier` is `tier_2` iff a Tier 2 delegation is active AND the Registry has populated Tier 2 fields; `tier_1` responses will carry `insufficient_data` for every rule whose conditions reference a Tier 2 field, and `upgrade_path` carries a Norwegian call-to-action pointing at the Altinn delegation flow. When `data_tier` is already `tier_2`, `upgrade_path` is null. Only rules whose citations have been human-verified against Lovdata (a required database migration — `legal_reference_verified_at IS NOT NULL`) reach this endpoint; unverified rules stay in staging until a human confirms them.

## Path parameters

- `org` string, required

## Response `200`

Obligations evaluated. Ordering is deterministic — `rule_id` ASC — per the evaluator's contract; repeated calls over unchanged rules + company data produce identical arrays.

- object
  - `success` true, required
  - `data` object, required
    - `org_number` string, required
    - `entity_type` string, required: Brønnøysund entity-type code (AS, ENK, ANS, DA, NUF, ...). Evaluator filters rules by matching this against each rule's `entity_types[]`.
    - `nace_codes` string[], required: NACE industry codes assigned to this company. An array because large entities have multiple; the first entry is the primary activity.
    - `data_tier` 'tier_1' | 'tier_2', required: `tier_2` iff the caller's Tier 2 delegation is active AND the Registry has populated tier_2 fields; `tier_1` otherwise. When tier_1, any rule reading a Tier 2 field surfaces as `insufficient_data` and `upgrade_path` is populated.
    - `obligations` EvaluationResult[], required: Every rule whose `entity_types[]` matches the company. Sorted by `rule_id` ASC deterministically. Agents branch on `evaluation_result` (applicable / not_applicable / insufficient_data).
      - `rule_id` string, required: Matches `rules.rule_id` in a required database migration.
      - `obligation_name` string, required: Obligation name taken from the rule's first outcome. Convenience for UI / agent rendering.
      - `description` string, required: Norwegian description passed through from the rule outcome.
      - `frequency` 'monthly' | 'bimonthly' | 'annual' | 'one_time' | 'continuous', required: How often this obligation recurs. Aligned with RuleOutcomeFrequency.
      - `legal_reference` string, required: Lovdata-style legal reference from the rule row.
      - `data_tier_required` 'tier_1' | 'tier_2', required: Highest tier any condition in this rule reads from. `tier_2` when ANY condition has `data_tier: tier_2`; `tier_1` otherwise. Lets agents pre-flight whether a delegation is required to re-evaluate.
      - `evaluation_result` 'applicable' | 'not_applicable' | 'insufficient_data', required: Verdict. `insufficient_data` means a Tier 2 field was null or missing — the agent should trigger the delegation flow rather than treat it as yes/no.
      - `reason` string, required: Human-readable explanation. English for `insufficient_data` (so agents in any locale can match on a stable substring), Norwegian where the outcome copy is Norwegian.
      - `deadline_rule` string, required: Stable identifier for the deadline-calculation routine. Consumed by the deadline engine to expand this obligation into concrete due dates. Empty string when the rule has no outcome or no deadline_rule.
    - `upgrade_path` string, nullable, required: Norwegian call-to-action pointing at the Altinn delegation flow + /recipes for the full walkthrough. Populated when `data_tier === 'tier_1'`, null when Tier 2 is already active.
    - `upgrade_path_en` string, nullable: English sibling of `upgrade_path` (the `summary`/`summary_en` `_en`-suffix convention). Same meaning and same tier gate: populated when `data_tier === 'tier_1'`, null when Tier 2 is already active. The Norwegian original stays on `upgrade_path` unchanged (append-only).
    - `rulebook_coverage` RulebookCoverage: Explicit Rulebook coverage signal. Brønnøysund uses ~30 entity-type codes but the Rulebook only carries rules for a subset (AS, ENK, ANS, DA, NUF today). A company whose entity type has NO rules previously returned bare empty obligations/deadlines arrays — indistinguishable from 'this company has no obligations', which agents then falsely reported. This block makes an empty array impossible to misread: `covered` means empty arrays are a real evaluation verdict; `entity_type_not_in_rulebook` means NOTHING was evaluated. Coverage is derived from the active rule set in the database (rules are data), so it flips to `covered` automatically when rules for a new entity type land — no code deploy.
      - `status` 'covered' | 'entity_type_not_in_rulebook', required: `covered` — at least one active rule matched the company's entity type. `entity_type_not_in_rulebook` — the Rulebook holds zero rules for this entity type; the obligations/deadlines arrays mean 'not evaluated', NOT 'no obligations exist'. Closed vocabulary, append-only.
      - `entity_type` string, required: The entity-type code resolved from Brønnøysund — an echo of the response's top-level `entity_type`, repeated here so the coverage block is self-contained when an agent forwards it.
      - `notice` string, nullable, required: English explanation of the coverage gap, present iff `status === 'entity_type_not_in_rulebook'` (null when covered). Directed at the agent deciding whether to trust an empty array: do NOT report the company as having no obligations — its actual obligations are outside current Rulebook coverage.
  - `_meta` RulebookTrustMetadata, required: Metadata included in every response for trust and verifiability.
    - `rulebook_version` string, required: Current Rulebook version. Internal rule-version records carry structured origin metadata (`initial_seed` | `human_review` | `lovdata_drift_response` | `audit_finding` | `customer_question` | `legal_correction`) for operator forensics, but that attribution is deliberately NOT exposed on public responses to avoid leaking operational signal.
    - `data_freshness` string, date-time, required: When this data was last fetched (ISO 8601 UTC).
    - `last_verified` string, date-time, required: When this data was last verified against source (ISO 8601 UTC).
    - `source` string, required: Origin of this data. Defaults to `apier.no`. The agent-readiness probe (`GET /api/v1/health/agent-readiness`) is the one surface that may instead emit `apier.no telemetry` — it does so when at least one of its endpoint rates came from measured live telemetry, and falls back to `apier.no` when every rate is a static default; all other endpoints always emit `apier.no`.
    - `data_source` string, required: Authoritative origin of the underlying data (listed alongside rulebook_version, data_freshness, last_verified, legal_basis for Rulebook-influenced endpoints). Distinct from `source` (the response origin): `data_source` identifies the authoritative data publisher — e.g. 'Brønnøysund Enhetsregisteret + Apier Universal Rulebook'. Present on registry-backed endpoints.
    - `served_from` 'cache' | 'live' | 'static': Cache-aware endpoints only — 'cache' when the response was served from the local copy, 'live' when the gateway just refreshed from the upstream, 'static' when the payload was computed deterministically from pure code with no DB or upstream read (e.g. /v1/public/deadlines). Absent on endpoints that don't carry this semantic.
    - `stale` boolean: Cache-aware endpoints only — true when the upstream was unreachable and a within-limit cached row was served as a fallback. Absent on normal responses.
    - `schema_version` string, required: OpenAPI contract version at the time of the response; matches `info.version`. Always present on every `/v1/*` response so a future schema break can be traced to the exact rows / audit events that predate / postdate it. Agent-facing machine interfaces (v1/capabilities, workflows.json) may override with their own narrower surface version; all other endpoints inherit the manifest-level version.
    - `legal_basis` string, required: Legal basis under which the response data is reused. Present on Rulebook-influenced endpoints (v1/company/{org}/obligations, /v1/company/{org}/deadlines). Common value: 'NLOD — public registry reuse'.
    - `rule_count` integer, required: Rule-evaluation count — total rules evaluated for this request. Present on endpoints that invoke the Rulebook evaluator (v1/company/{org}/obligations).
    - `applicable_count` integer, required: Count of rules whose evaluation_result is 'applicable'. Present on evaluator endpoints.
    - `not_applicable_count` integer, required: Count of rules whose evaluation_result is 'not_applicable'. Present on evaluator endpoints.
    - `insufficient_data_count` integer, required: Count of rules whose evaluation_result is 'insufficient_data' (Tier 2 gated). Present on evaluator endpoints. rule_count = applicable_count + not_applicable_count + insufficient_data_count.
    - `cache_age_ms` integer, nullable: Cache layer: milliseconds since the cached row was computed, or null on a cache miss (served_from === 'live'). Agents use it alongside data_freshness as a staleness signal. Present on endpoints wired to the cache (v1/company/{org}/obligations, /deadlines, /summary, /v1/public/obligations, /v1/public/deadlines).
    - `response_time_ms` integer: Speed signal: total server-side processing time in milliseconds, measured via performance.now() at the route boundary. Mirrored on the `X-Apier-Response-Time-Ms` header so agents can key on it without parsing the body. Present on every endpoint.
    - `response_timestamp` string, date-time: RFC 3339 / ISO 8601 UTC timestamp stamped by the response builder at wire-exit. Mirrored on the `provenance_log.response_timestamp` column by a fire-and-forget writer. Distinct from `data_freshness` (when upstream data was fetched) and `last_verified` (when the citation was verified); this is the moment the envelope left the server. Always populated at runtime — deliberately left out of the `required` list to avoid a cascading contract change that would invalidate every pre-existing example envelope in this spec (append-only response contracts). A future revision may promote it into the `required` list alongside a bulk example refresh.
    - `response_hash` string: SHA-256 hash of the canonical-JSON form of the envelope with `_meta` stripped before hashing, prefixed with `sha256:`. Mirrored on `provenance_log.response_hash` so a consumer can independently re-hash the bytes they received and compare against what we persisted (integrity receipt). Stripping `_meta` is load-bearing: volatile fields (response_time_ms, cache_age_ms, served_from) and the hash itself would otherwise feed into the digest and break the cache-hit-bytewise-identical invariant.
    - `source_snapshot_id` string: Optional free-text pointer into an upstream sync snapshot the response derives from — e.g. a Brreg sync's `brreg-<ISO>` snapshot id. Absent when the response is not tied to a specific upstream snapshot (capabilities, tools, static deadlines).
    - `is_sandbox` true: Present and `true` only when the response was generated from sandbox fixture data (currently `ALTINN_MODE=sandbox` on `/api/v1/altinn/list-acting-capacity`). Absent (NOT `false`) on every other response — the absent-vs-false distinction is deliberate so downstream agents branching on `if (response._meta.is_sandbox)` cannot be misled into treating non-sandbox responses as positively-confirmed-not-sandbox. Distinct from the `/v1/sandbox/*` `is_sandbox: true` literal in `SandboxMeta` (which carries the sandbox surface tag); this flag rides through the production `/api/v1/altinn/*` surface to forensically tag a sandbox-mode response that an OEM evaluator received.
    - `cost_nok` number: What this call debited from the caller's prepaid credit balance, in NOK, rendered from the integer-øre ledger (50 øre → 0.5; the ledger itself never leaves whole øre and no float arithmetic touches a balance). Present on the 2xx body of every metered company-data read — the same debit that sets the `X-Credits-Cost-Ore` header, so the two never disagree. `0` when nothing was charged: credit enforcement running dark (the response then also carries `X-Credit-Check: shadow`) or the sandbox surface. Absent on unmetered endpoints and on error envelopes — a refunded 5xx/403/404 claims no cost rather than a wrong one. Lives under `_meta`, which `response_hash` excludes, so the provenance receipt is unaffected; the route's ETag is computed before the credit wrapper stamps it, so a conditional request can still short-circuit to 304. Append-only addition.
    - `wallet_remaining_nok` number, nullable: The prepaid credit balance remaining AFTER this call's debit, in NOK (same rendering as `cost_nok`; mirrors the `X-Credits-Balance-Ore` header). `null` when no balance was read: credit enforcement running dark, or the sandbox surface. Present wherever `cost_nok` is. An agent planning a sequence of metered calls can divide this by the per-call price from GET /api/v1/pricing to know how many reads remain before a 402 INSUFFICIENT_CREDITS. Append-only addition.
    - `spend_cap_remaining_nok` number: What the calling key may still spend under its tighter spend cap (Europe/Oslo calendar day or month) AFTER this call's debit, in NOK (same rendering as `cost_nok`; never below 0). Present on the 2xx body of a metered read only when credit enforcement is live AND the key has a daily or monthly cap (set with PATCH /api/v1/account/keys/{id}); absent otherwise. When it reaches 0 the next metered call on this key returns 402 SPEND_CAP_REACHED until the cap resets. Append-only addition.

## Other responses

- `400`: Invalid org path parameter (must be exactly 9 digits, no whitespace, no hyphens). The error `_meta` carries `data_source`, `legal_basis`, and `schema_version` so clients on the error path see the same Rulebook provenance as 200 responses.
- `401`: Authentication failed — missing, malformed, invalid, or revoked API key. Middleware-generated but enriched at the route boundary so the envelope's `_meta` carries the Rulebook-required `data_source`, `legal_basis`, and `schema_version`.
- `402`: Prepaid credit balance does not cover this call. Emitted ONLY when credit enforcement is live (CREDITS_LIVE=true); while enforcement runs dark — the launch default — responses carry `X-Credit-Check: shadow` instead and a 402 is impossible. The debit is CONDITIONAL: nothing was charged for this 402. The balance is checked-and-debited atomically BEFORE the handler runs, so an insufficient balance leaves both the balance and the ledger untouched. Body is the standard Rulebook error envelope plus the machine-readable payment-recovery contract: `top_up_url` (absolute URL to the billing dashboard where a human tops up the key's prepaid balance), `balance_ore` (the observed balance at rejection time), and `cost_ore` (this call's price) — together with the catalog-derived `retryable`/`fix_hint`/`docs_url` fields, a stranded agent can compute the shortfall and self-recover from this body alone. Discover all prices without auth at GET /api/v1/pricing. Agents should surface top_up_url as a human-handover link rather than retry: with an unchanged balance the endpoint returns this 402 deterministically. The same status carries a second, distinct refusal: 402 SPEND_CAP_REACHED, when the key's own Europe/Oslo daily or monthly spend cap (set with PATCH /api/v1/account/keys/{id}) would be exceeded. It is checked inside the same atomic RPC BEFORE the debit, so it too charges nothing and writes no ledger row. Branch on `error_code`: SPEND_CAP_REACHED carries `cap`, `cap_ore`, `spent_ore`, `cost_ore` and `resets_at` plus a Retry-After header, is `retryable: true` (the identical call succeeds after `resets_at`), and carries no `top_up_url`: topping up does not lift a cap. Like INSUFFICIENT_CREDITS it occurs only while enforcement is live.
- `404`: Organisation does not exist in Brønnøysund Enhetsregisteret. Authoritative — the BRREG live API returned 404.
- `429`: Authenticated rate limit reached on a Rulebook-influenced endpoint (`/v1/company/{org}/obligations`, `/v1/company/{org}/summary`). Same two-dimensional shape as `RateLimitExceeded` (per-(api_key, endpoint) per-minute AND per-(api_key, org_number) per-day, with `X-RateLimit-Dimension: per_key | per_org | both` identifying which bucket tripped). Body schema is `RulebookApiErrorWithStrictProvenance` — composes the Rulebook trust-metadata contract (`_meta.data_source` + `_meta.legal_basis` REQUIRED) AND the strict-provenance contract (`_meta.response_timestamp` + `_meta.response_hash` REQUIRED, Feature A) so clients see NEITHER side weakened on the 429 path. The generic `RateLimitExceeded` uses `ApiErrorWithStrictProvenance` which drops Rulebook fields; a Rulebook-only envelope would drop response_timestamp + response_hash. This composite component is the canonical fix and the only 429 component on the Rulebook surface.
- `500`: Unexpected failure while evaluating obligations (rule fetch, evaluator, or Supabase error). Internal details never leak in the response body; the cause is captured to Sentry server-side. A 500 here also surfaces when a required database migration has not been applied to the target environment — `getActiveRules` filters `legal_reference_verified_at IS NOT NULL`, so the missing column fails the rule query rather than degrading to an empty obligations array.
- `503`: Brønnøysund is unreachable (retry budget exhausted on 5xx / network / timeout). Distinct from 404: an unknown org returns 404 NOT_FOUND, while a transient upstream failure returns 503 UPSTREAM_UNAVAILABLE. The response explanation names `Brønnøysund` as `upstream_system` so agents can branch on it.

---

[API](https://skmtc.dev/apier/apis/apier-no-api.md) · [All operations](https://skmtc.dev/apier/apis/apier-no-api/llms.txt) · [OpenAPI document](https://skmtc.dev/apier/apis/apier-no-api/revisions/9ec19bc87311?raw)
