How Altinn 3 System Users Work
The two delegation models in Altinn 3, why System Users exist, and the three-leg setup an agent needs before it can act on behalf of a Norwegian company.
[Cite this as: Apier.no Docs v0.1.0 — last updated 2026-05-09]
What this guide covers
This guide explains how an AI agent can act on behalf of a Norwegian company through Altinn 3. It walks through the difference between the two delegation models (personal user vs System User), why System Users exist, the three-leg setup that has to be in place before a System User can do anything useful, and where Apier fits into the chain. The factual content here is sourced strictly from already-merged repository material — the Maskinporten Developer Guide, the Altinn adapter under src/lib/altinn/, and the Maskinporten client under src/lib/maskinporten/. For procedural how-tos on the Norwegian government portals themselves, this guide links to authoritative Digdir documentation rather than reproducing steps that drift over time.
Altinn 3 in one minute
Altinn is the Norwegian government's digital services platform. Altinn 3 is the current generation, distinct from the older Altinn 2 surface that is being deprecated. From an integrating-application perspective, the practical changes are:
- Altinn 3 is API-first and built on the same Maskinporten OAuth2 layer as the rest of Norwegian government infrastructure. Tokens authenticate the calling organization rather than a human session.
- Identifiers and resource URIs differ from Altinn 2 — agents that depend on an Altinn 2 service code or role code cannot reuse the same string against Altinn 3 without translation.
- Delegation is modelled differently: System Users (described below) are the Altinn 3 mechanism for "this organization is acting on behalf of that organization", whereas Altinn 2 used a combination of organization roles and Altinn-internal rights.
The companion Maskinporten Developer Guide covers the OAuth2 token flow that underlies Altinn 3 calls. Reading it first is recommended; this guide assumes you understand what a Maskinporten access token is and how it gets issued.
Personal user vs System User — the two delegation models
There are two ways an actor can perform an Altinn action on behalf of an organization:
-
Personal user, BankID-authenticated. A human signs in with BankID or ID-porten, Altinn maps that identity to the organizations they have a role in, and the action proceeds under that human's authority. This is the default for most filing flows — a daglig leder filing the company's MVA-melding, an accountant filing on behalf of a client through a personal Regnskapsfører role.
-
System User. An organization (the integrating party) is registered in Altinn as a non-human actor that other organizations can grant rights to. The System User authenticates via a Maskinporten access token issued for the integrating organization. There is no human identity in the loop at request time; authority comes from a delegation the target organization explicitly granted in advance.
These models are complementary. Some flows demand a personal user (anything that requires human consent at signing time). Recurring, programmatic, no-human-in-loop work only becomes reliable when there is a System User behind it.
Why System Users exist
The Maskinporten + System Users architecture solves a specific problem: how do you let a piece of software file MVA on behalf of a thousand different companies, every quarter, without a human logging in and clicking through Altinn for each one? The personal-user model breaks down at scale — it requires per-action human authentication, ties every action to that human's continued employment, and leaks personal identity into machine-to-machine traffic.
The System User model decouples the integrating party from the human chain. Once the target company has granted rights to the System User in Altinn, the integrating party's automation can act on those rights without re-authenticating a human. The audit trail records which System User performed the action, and the target company can revoke the delegation at any time.
Concretely: if you are building software that needs to file MVA, A-melding, or skattemelding on behalf of clients, fetch restricted Tier 2 data about a company that is not yours, or perform any delegated submission, approval, or signing action — you will need a System User. The Maskinporten guide flagged a particularly nasty pitfall: a System User that exists but has no rights granted to it. Authentication succeeds; action fails. Is the System User present? and does it have the right permissions? are two separate questions.
The three-leg setup
Standing up a System User requires three independent pieces of infrastructure to be in place. None of them is optional. The merged Maskinporten guide walks through each in detail; this section is a high-level map.
-
Leg 1 — Maskinporten OAuth2 client. Your integrating organization needs a Maskinporten client registered against either the test or production environment. The client identifies the integrating party and is bound to a virksomhetssertifikat (your organization's hardware-issued digital certificate from Buypass or Commfides) plus a JWK upload. This is the "your software can authenticate to the Norwegian government" part. See the Maskinporten guide for the JWT signing flow, scope semantics, and the full activation chain.
-
Leg 2 — Samarbeidsportalen onboarding. Before Maskinporten will issue tokens against the live environment, your integrating organization must sign Digdir's bruksvilkår (terms of use) for Maskinporten and for any downstream services you plan to call. This is a one-time legal-administrative step, performed in the Samarbeidsportalen by someone with signature authority for your organization. The procedural specifics live at docs.digdir.no — they change periodically, so do not paste step-by-step screenshots into this kind of guide.
-
Leg 3 — Altinn System Register registration plus per-target delegation. Your integrating party registers a System User definition in Altinn. Each target company (the organization you want to act on behalf of) must then add your System User in their own Altinn portal and grant specific Altinn rights to it — for example a Regnskapsfører-equivalent right for accounting workflows. Until the target company has both added the System User and granted rights, your authenticated Maskinporten token cannot perform delegated actions for them.
The three legs interlock. A working Maskinporten client without a Samarbeidsportalen onboarding cannot reach the live API. A live-onboarded client without an Altinn System User registration cannot act on behalf of anyone. An Altinn System User registration without a per-target delegation cannot perform actions for that specific target company.
Bruksvilkår and Registreringsskjema flow (link out, do not paste)
Both the Maskinporten bruksvilkår signing and the Altinn System User registreringsskjema are bureaucratic flows that change without API-level notice. This guide deliberately does not reproduce the click-by-click procedure — a copy would drift the moment Digdir or Altinn updates their portal. Authoritative references:
- docs.digdir.no for Maskinporten bruksvilkår, JWK upload, scope application, and Samarbeidsportalen mechanics.
- altinn.no for Altinn System User registration, per-target delegation, and the right (rettighet) catalogue.
Treat both portals as the source of truth; verify every form field against the live page before relying on it.
Scopes — the namespace pattern
Maskinporten access tokens carry one or more scopes. Each scope is a string that names a permission on a downstream service. Apier's Maskinporten client manages scope strings as opaque values — they are not interpreted on the client side, only echoed in the JWT request and validated by Maskinporten and the downstream service.
The Altinn-relevant scopes follow a altinn:<surface>/<resource> pattern (for example, scopes under the altinn:authentication and altinn:instances namespaces cover the System User authentication surface and the instance-submission surface respectively). The exact list of available scopes is published by Digdir; do not hand-type them — always copy from the authoritative Digdir scope catalogue. The Maskinporten guide covers the case-sensitivity pitfall in detail (one of the most common day-loss failures on the integrator side is a missing colon or wrong slash in a scope name).
How Apier wires this together
Apier's Auth Gateway abstracts most of the chain above. Two endpoints are most relevant to a downstream agent:
POST /api/v1/auth/system-user/delegate— orchestrates the System User delegation flow for a target organization. The request body identifies the target org and the desired scope set; the response confirms the delegation status. The route layer holds the Maskinporten access token, performs the Altinn round-trip, and writes an audit row.GET /api/v1/auth/permissions/{org}— returns the current authoritative permission set for the calling consumer's relationship with the named target organization. Use this to confirm that a delegation is in fact in place before attempting an action; do not rely on cached state.
The internals — virksomhetssertifikat handling, JWT signing, token caching, scope assertion — are not exposed to the agent. The agent presents an Apier API key in the standard Authorization: Bearer apier_test_<your_key_here> format and Apier produces the Maskinporten + Altinn round-trip on its behalf. A correctly-delegated request looks like:
curl -H 'Authorization: Bearer apier_test_<your_key_here>' \
https://apier.no/api/v1/auth/permissions/999999999The response surfaces the System User's effective permission set against the target organization, sourced directly from Altinn at request time.
Limitations — what System Users cannot do
System Users are powerful for unattended automation but they are not a universal substitute for a personal user. The boundaries that matter:
- Step-up actions still require a personal user. Anything that the Norwegian government has classified as requiring a human signing event (BankID-level identity assertion at action time, certain high-trust workflows) falls outside the System User model. The action will be refused at the Altinn layer regardless of how the System User is configured. The Compliance Explainer surfaces these as structured errors with a handover field naming the role that needs to step in.
- Delegations can be revoked at any time. A target organization can withdraw a System User's rights through Altinn without warning. Cached permission state goes stale instantly when this happens; always re-verify through
GET /api/v1/auth/permissions/{org}before acting on a delegation that may be older than a few minutes. - Maskinporten token lifetime is short. Tokens expire on the order of minutes (the Maskinporten guide cites 120 seconds as the canonical figure for the test environment; production may differ). An agent that hard-codes or persists a token to disk will start failing the moment it expires. Apier's Auth Gateway caches in memory and refreshes on demand; if you are integrating against Maskinporten directly, follow the same pattern.
- A System User without rights authenticates but cannot act. This is the most common pitfall, called out in the Maskinporten guide. Treat can the System User authenticate? and does the System User have the required rights for this target company? as two separate questions. Apier's
permissionsendpoint answers the second.
For deep coverage of the OAuth2 layer underneath all of this, see the Maskinporten Developer Guide. For the obligation model an agent reasons about once it has the authority to act, see the companion Norwegian company obligations guide.
Understanding Norwegian Company Obligations
How Apier models Norwegian regulatory obligations as versioned data — the rules, deadlines, and entity-type nuances an agent needs to reason correctly.
Maskinporten Production Setup
Configure the Maskinporten live integration, interpret MASKINPORTEN_AUTH_FAILED, and run the readiness probe before cutover.