Company

Read consumer's own audit trail for a company

Returns the slice of the immutable Sporingslogg (audit_log table) that THIS consumer wrote against the URL's org_number. Cross-consumer visibility is structurally impossible — the reader filters on consumer_id = <authed-consumer> AND org_number = <url-org> as a parameterized binding before any other predicate, and rows belonging to any other consumer never appear regardless of scope, role, or operator status. Useful for consumers reconciling what their own agents did (reading every delegation.create / gov_api.call row an agent generated for a company — see the closed action enum below for the full vocabulary), AI-agent operators debugging filing flows (filter on initiated_by=agent), and dispute defense (Skatteforvaltningsforskriften and bokføringsloven both impose retention obligations on the agent of record; this endpoint provides the forensic trail). The response surfaces correlation_id (joins to provenance_log, evaluation_snapshots, compliance_state_events from the same request), initiated_byschema_version (the OpenAPI contract version at write time so a future schema break is traceable). Sensitive keys in the details JSONB are AUTO-REDACTED to [REDACTED] by the read-side scrubber (deny-list pattern: any key containing token / secret / password / bearer / authorization / jwt / api_key / private_key / credential / client_secret / refresh_token, case-insensitive); the write-side redactor is the primary defence and the read-side scrubber is belt-and-suspenders for any pre-correlation-id rows. Pagination is keyset on (timestamp DESC, id DESC) with limit + 1 lookahead — next_before and next_before_id from the previous response form the cursor for the next page; rows with identical timestamps tiebreak deterministically on id so a paged scan never duplicates or skips. Empty result for a valid (consumer, org) pair returns 200 with the full envelope data: { data: [], pagination: { limit, has_more: false } } (NEVER 404 — that would leak existence across consumers). Query parameters validated by Zod at route boundary: limit is z.coerce.number().int().min(1).max(200).default(50) — string→number coercion of valid numeric inputs (?limit=50 → 50) IS part of the contract because URL query parameters arrive as strings via URLSearchParams; non-numeric or out-of-range inputs (?limit=abc, ?limit=0, ?limit=999) fail validation explicitly rather than silently normalising; before is z.string().datetime({ offset: true }); before_id is z.string().uuid(); since and until are z.string().datetime({ offset: true }) (the { offset: true } modifier accepts ISO 8601 with explicit Z or +HH:MM offset — bare local times are rejected); action and initiated_by are closed enums (see schemas). Validation uses safeParse returning a structured 400 response with error_code: VALIDATION_FAILED and per-field details[] on any failure — no swallowed errors, no silent dropping of invalid fields. Source:.

get/api/v1/company/{org}/audit

Request

  • Base URL: https://www.apier.no
  • URL: https://www.apier.no/api/v1/company/{org}/audit
  • Auth: HTTP bearer

Path parameters

orgstring required

9-digit Norwegian organisation number (Brønnøysund-issued). Used as a within-namespace filter — the auth boundary is the API key's resolved consumer_id, not this URL parameter. Any other shape returns 400 VALIDATION_FAILED before the audit table is touched.

Query parameters

limitinteger

Page size. Defaults to 50; max 200. Internally the reader fetches limit+1 to compute has_more without an extra COUNT round-trip — the (limit+1)-th row is sliced off and only its presence is surfaced via pagination.has_more.

cursorstring

Opaque HMAC-signed continuation token - the CANONICAL pagination idiom. Pass the previous response's pagination.next_cursor back verbatim; a tampered or cross-endpoint cursor is rejected with 400 CURSOR_INVALID. Cannot be combined with the legacy before/before_id tuple.

beforestring date-time

Keyset cursor — pass pagination.next_before from the previous response. Combined with before_id; supplying one without the other returns 400 VALIDATION_FAILED (the cursor is a tuple, not two independent fields). Returns rows STRICTLY OLDER than the (timestamp, id) tuple. DEPRECATED: use the opaque cursor parameter instead; this parameter keeps working through the deprecation window (Sunset: 2027-01-31T00:00:00Z) and responses to requests using it carry Deprecation/Sunset/Link headers.

before_idstring uuid

Keyset cursor companion — pass pagination.next_before_id from the previous response. The id tiebreak ensures rows with identical timestamps page deterministically (never duplicated, never skipped) under concurrent writes. DEPRECATED: use the opaque cursor parameter instead; this parameter keeps working through the deprecation window (Sunset: 2027-01-31T00:00:00Z) and responses to requests using it carry Deprecation/Sunset/Link headers.

sincestring date-time

Inclusive lower bound on timestamp, RFC 3339 with timezone (Z or +HH:MM both accepted). Compared as Date instants, so a mixed-offset (since=Z, until=+02:00) range is correctly ordered.

untilstring date-time

Inclusive upper bound on timestamp, RFC 3339 with timezone. If both since and until are present, since <= until (compared as instants); otherwise 400 VALIDATION_FAILED with a field-level message.

action'delegation.create' | 'delegation.revoke' | 'approval_token.mint' | 'approval_token.used' | 'api_key.create' | 'api_key.revoke' | 'gov_api.call' | 'registry.upsert' | 'system.cron_run' | 'privacy.dsr' | 'subscription.create' | 'subscription.delete' | 'webhook.delivered' | 'dry_run_execute' | 'risk_elevated_response' | 'risk_elevated_shadow' | 'risk_pattern_override_applied' | 'submit_mva_started' | 'submit_mva' | 'submit_mva_failed' | 'execute_authorization_failed' | 'rate_limit_blocked' | 'idempotency_replay' | 'altinn.list_acting_capacity' | 'brreg.get_company_profile' | 'write_conflict_blocked'

Closed enumeration of audit_log action identifiers — single source of truth for both response bodies and query-parameter filters on the audit-trail read surface. Mirrors AUDIT_ACTIONS Adding a new value is a one-line append HERE that propagates via $ref to every consumer. Append-only — renaming a value is a /v2 break.

Filter to one specific audit action. Whitelisted enum — see the shared AuditAction schema for the full vocabulary. Anything outside the list returns 400 VALIDATION_FAILED. Both this query parameter AND the response body's action field $ref the same schema component, so adding a new value happens in ONE place.

initiated_by'human' | 'agent' | 'cron' | 'system' | 'unknown'

Closed enumeration of initiated_by classifier values — single source of truth for both response bodies and query-parameter filters on the audit-trail read surface. Mirrors INITIATED_BY_VALUEShuman = write action confirmed via the X-Approval-Token UI flow. agent = self-identifying AI client OR an unattended write without approval. cron = scheduled job hitting /api/cron/* with the configured CRON_SECRET. system = reserved for future internal service-to-service calls. unknown = read verbs without other signals, plus the historical-row backfill default for pre-correlation-id rows.

Filter by initiator classification — see the shared AuditInitiatedBy schema for the full enum semantics. Both this query parameter AND the response body's initiated_by field $ref the same schema component.

Response

Page of audit entries for THIS consumer × THIS org, ordered timestamp DESC, id DESC. Pagination via the next_before + next_before_id cursor pair when has_more is true. Empty data array when the consumer has no audit rows for the org (NEVER 404 — that would leak existence across consumers).

successtrue required

Example response

{
  "data": {
    "data": [
      {
        "org_number": "999999999",
        "gov_api_response_status": 201
      }
    ]
  },
  "_meta": {
    "rulebook_version": "v1.0.0",
    "source": "apier.no",
    "data_source": "Brønnøysund Enhetsregisteret + Apier Universal Rulebook",
    "schema_version": "1.0.0",
    "legal_basis": "NLOD — public registry reuse",
    "response_timestamp": "2026-04-24T12:00:00.000Z",
    "response_hash": "sha256:0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
    "source_snapshot_id": "brreg-2026-04-24T02:00:00.000Z",
    "cost_nok": 0.5,
    "wallet_remaining_nok": 9.5,
    "spend_cap_remaining_nok": 12.5
  }
}

Changes

No recorded changes to this operation across all 1 revision of this API.