- What the integration does
- In plain terms — without the jargon
- Digdir / Maskinporten: client, JWT grant and scopes
- System user: System Register, request and BankID approval
- Access packages vs. rights
- Tokens: Maskinporten token and Altinn token exchange
- Per service: tax card, VAT, annual accounts, business specification, tax return
- Pitfalls worth avoiding
- What a customer has to do (BankID approval)
What the integration does
Not technical? Skip straight to "In plain terms — without the jargon" further down, and get the whole picture in everyday words.
Macct submits to the public authorities on behalf of the customer, without the customer sharing a password or logging in manually. The following happens automatically:
- Tax card for employers — fetches from Skatteetaten (the Norwegian Tax Administration) how much tax to withhold from employees' pay.
- VAT return — the value-added-tax statement; delivered via an Altinn 3 app hosted by Skatteetaten.
- Business specification + tax return (limited company) — the underlying figures (formerly called RF-1167) and the company's tax return itself.
- Annual accounts — submitted as form RR0002 to the Register of Company Accounts in Brønnøysund via Altinn.
- A-melding (payroll report) and shareholder register statement — the monthly payroll-and-tax report, and the record of who owns the shares — both to Skatteetaten.
Three building blocks make this possible: Maskinporten (a kind of ID card that lets one computer prove who it is to another — run by the state via Digdir), a system user (the authorisation you give Macct, approved with BankID in Altinn), and Altinn / Skatteetaten (where the submission is actually delivered). The Brønnøysund registers are used to check the organisation number, your role and that the company is in good standing when you register. All three are explained more fully just below.
In plain terms — without the jargon
Most of this page is technical. Here is the same thing in plain English, using a picture you will recognise from everyday life.
Think of the public authorities — Skatteetaten, Brønnøysund — as a set of locked offices where you hand in paperwork. Normally you go there yourself, log in with BankID and submit. Macct does that job for you. But for a computer to be let in and submit on your behalf, three things have to be in place:
- 1. An ID card for machines (Maskinporten). Just as you show your BankID, the Macct machine has to prove who it is. Maskinporten — a state service from Digdir — gives Macct a digital "ID card" that renews itself automatically. No humans log in; it is machine talking to machine.
- 2. An authorisation from you (the system user). The ID card only says "this is Macct". It does not say that Macct may act for your company specifically. So you sign, once, with BankID an authorisation: "Macct may submit VAT, annual accounts and the like for my company." This authorisation is called a system user. It is limited to exactly what it says, it is traceable, and you can withdraw it at any time.
- 3. The delivery window itself (Altinn / Skatteetaten's APIs). With the ID card and the authorisation in hand, Macct goes to the right "window" at the authorities, hands in the document and gets a receipt back.
In short: Maskinporten = who the machine is. System user = what it is allowed to do, and for whom. Altinn = where it submits. The rest of this page is the detail behind each of those three.
What do you notice as a customer? Almost nothing. You approve one link with BankID the very first time. After that Macct keeps the books and prepares the submissions, and you press "send" when you are ready. Nothing goes off automatically — neither to Skatteetaten nor to Brønnøysund — without your approval.
Digdir / Maskinporten: client, JWT grant and scopes
In short: Macct asks the state for a temporary access pass by presenting a signed digital "stamp". The pass only covers the tasks Macct has been approved for in advance — called scopes — for example fetching tax cards or submitting VAT.
Maskinporten is Digdir's OAuth2 service for machine-to-machine (M2M). The software
system has one client per environment (test and production kept separate),
authenticated with an enterprise certificate / a key registered in the
collaboration portal (Samarbeidsportalen). Tokens are obtained with
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer: a signed JWT
assertion is exchanged for an access token for the scopes the client has been
granted.
POST https://maskinporten.no/token
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer&
assertion=<signed JWT: iss=clientId, aud=maskinporten, scope=...>
The scopes we use
| Scope | For what |
|---|---|
skatteetaten:skattekorttilarbeidsgiver | Fetch the electronic tax card |
skatteetaten:mvameldingvalidering | Pre-validation of the VAT return (see pitfall) |
altinn:instances.write | Create/write Altinn 3 app instances (VAT, tax return, annual accounts) |
altinn:authentication/systemregister.write | Register/update the system in the System Register |
altinn:authentication/systemuser.request.read / .write | Create and read system user requests |
skatteetaten:skattekorttilarbeidsgiver — a small deviation gives
invalid_scope and no explanation. Maskinporten also rejects the
entire token request if just one scope in the set is not granted, so the
test and production clients should each have their own scope set (production has,
for example, the VAT scopes that test does not).
System user: System Register, request and BankID approval
In short: This is your actual authorisation, and it is set up in three steps: Macct registers itself as a "system" with Altinn (done only once), then creates a request for your company, and finally you approve it with BankID. Only then can Macct submit on your behalf.
A system user is the customer's authorisation of the software system in Altinn. The flow has three steps:
1. Register the system (once per environment)
The software system is registered in Altinn's System Register with a system ID of
the form <vendor-orgnr>_macct, the client ID(s) from Maskinporten,
and which rights and access packages the system manages.
POST {altinn}/authentication/api/v1/systemregister/vendor
{ "id": "<orgnr>_macct", "vendor": { "ID": "0192:<orgnr>" },
"clientId": ["..."], "rights": [...], "accessPackages": [...],
"allowedRedirectUrls": ["https://macct.no/altinn/callback"] }
2. Create a system user request per customer
POST {altinn}/authentication/api/v1/systemuser/request/vendor
{ "systemId": "<orgnr>_macct",
"partyOrgNo": "<customer's orgnr>",
"externalRef": "selskap-123",
"rights": [ { "resource": [ { "id": "urn:altinn:resource", "value": "app_skd_formueinntekt-skattemelding-v2" } ] }, ... ],
"accessPackages": [ { "urn": "urn:altinn:accesspackage:merverdiavgift" }, ... ],
"redirectUrl": "https://macct.no/altinn/callback" }
→ the response contains a confirmUrl (am.ui.altinn.no/.../systemuser/request?id=...)
3. The customer approves with BankID
The customer opens the confirmUrl and approves in Altinn. After
approval, the actual system user is looked up (the "bysystem" list), and a
systemUserId is stored on the customer. It is not used directly in the
token — the authorisation itself is carried by externalRef + the
customer's organisation number (below).
externalRef must be unique per system
user. If a customer needs a new system user (for example with extended
access) without losing the old one, the new one must be created with a different
externalRef — otherwise Altinn replies that a system user already
exists for the system ID. A tidy convention (selskap-123,
selskap-123-mva) keeps this manageable.
Access packages vs. rights
In short: Altinn requires two kinds of access at the same time — a broad "role bundle" (that Macct may work with accounting and VAT at all) and a specific "key" to each individual service. If either of the two is missing, the submission is rejected. Macct sets up both for you.
Altinn 3 distinguishes between two types of authorisation, and submission often requires both:
- Rights — point to a specific resource/app, e.g.
app_skd_formueinntekt-skattemelding-v2(tax return),app_brg_aarsregnskap-vanlig-202406(annual accounts),ske-innrapportering-amelding(a-melding). - Access packages — role-based "bundles" that Altinn's policy
engine (PDP) requires in order to instantiate certain apps. We use
urn:altinn:accesspackage:regnskap-okonomi-rapportandurn:altinn:accesspackage:merverdiavgift.
AUTH-00063 "accesspackage is not
found in the referenced system". The System Register is environment-split, so
packages added in test must also be added in prod. Rights alone (without an access
package) tend to give a 403 from the PDP when the app is to be instantiated.
Tokens: Maskinporten token and Altinn token exchange
In short: The access pass from Maskinporten is exchanged for a "building-specific" pass at Altinn, and tied to your authorisation so the submission lands on the right company. Test companies and real companies use separate systems — they must never be mixed, or Altinn won't find the authorisation.
To act on behalf of an enterprise other than the client owner, we bind the token to
the system user via authorization_details (the RAR type
urn:altinn:systemuser):
authorization_details = [{
"type": "urn:altinn:systemuser",
"systemuser_org": { "authority": "iso6523-actorid-upis", "ID": "0192:<customer's orgnr>" },
"externalRef": "selskap-123"
}]
The Maskinporten token is then exchanged for an Altinn token to reach the Storage/App APIs:
GET {altinn}/authentication/api/v1/exchange/maskinporten
Authorization: Bearer <maskinporten token with altinn:instances.write>
→ Altinn JWT used against app instances
maskinporten.no
+ platform.altinn.no, test/demo to test.maskinporten.no +
platform.tt02.altinn.no. If the environments are mixed, the system user
does not resolve (404 / MP-303). We choose the environment per company, not
globally.
Per service: API calls and parameters
Tax card for employers
Directly against Skatteetaten's "Tax card for employers" (v3, advance-tax API) with
a system-user-bound Maskinporten token and the scope
skatteetaten:skattekorttilarbeidsgiver. Host:
api.skatteetaten.no (prod) / api-test.sits.no (test).
Parameters: income year, the employer's organisation number and the employee's
national identity number. Response: deduction type (table/percentage), table number
and deduction rate — which are written onto the employee and used in the payroll
run.
VAT return
Delivered via the Altinn 3 app mva-melding-innsending-v1
(instances.write + system user), not the discontinued direct API. Two XML
documents are built: the return itself (mvamelding, namespace
skattemeldingformerverdiavgift) and a submission wrapper
(mvameldinginnsending). Flow:
1) POST .../instances (create instance, instanceOwner = customer's orgnr)
2) PUT/POST data: mvamelding + wrapper (replace the auto-created element)
3) PUT .../process/next (data → confirmation → feedback)
→ receipt: instanceOwnerPartyId/instanceGuid
The return contains, among other things, skattleggingsperiode (a
two-month term + year), fastsattMerverdiavgift,
mvaSpesifikasjonslinje[], meldingskategori=alminnelig and
skattepliktig>organisasjonsnummer. Optional pre-validation is
available at /api/mva/grensesnittstoette/mva-melding/valider.
Annual accounts (RR0002)
To the Register of Company Accounts via the Altinn app
app_brg_aarsregnskap-vanlig-202406. The -202406 suffix is a
version date (June 2024) that Brønnøysund can roll when they publish a new yearly
version of the app — so the name is configurable on our side rather than hardcoded,
and it may differ from what is shown here if Brreg has released a newer version. Two
dataTypes are uploaded: Hovedskjema (RR0002H_M — metadata) and
Underskjema (RR0002U_M — profit/loss and balance sheet with detail
lines). The process is taken to PROSESS_FULLFORT, which is the receipt
that the submission has been completed.
Business specification and tax return (limited company)
The business specification (the RF-1167 basis) is built and approved first; then the
company's tax return is generated (v2 format,
skattemeldingForFormuesOgInntektsskatt, packaged in
skattemeldingOgNaeringsspesifikasjonRequest with base64-encoded
sub-documents) and delivered via app_skd_formueinntekt-skattemelding-v2.
Submission is never automatic: the status flow is
DRAFT → READY_FOR_REVIEW → APPROVED → SUBMITTED with a SHA-256
integrity check at every step and a mandatory preflight check (requiring, among
other things, a completed year-end close and explicit approval) before anything is
sent.
BigDecimal with two decimals, and foreign currency is converted at
Norges Bank's rate on the transaction date. No submission happens unless it has been
triggered and approved — the system is built never to send anything "on its own".
-202406,
several of the names carry a version or date token — -v2 for the tax
return, -v1 for the VAT app, v3 for the tax-card API — that
Skatteetaten and Brønnøysund can upgrade over time. All of them are configurable in
Macct, so the live integration follows the current version even if the names in this
text fall behind.
Pitfalls worth avoiding
The points below are the ones that typically cost the most time. All are handled in Macct.
api.skatteetaten.no. The host
idporten.api.skatteetaten.no validates ID-porten keys and replies 401
to a Maskinporten token — the right host is decisive.applicationmetadata — e.g. the
annual accounts' main document is called Hovedskjema (not "Skjema"),
and the VAT app is called mva-melding-innsending-v1.norskIdentifikator must wrap an
<organisasjonsnummer>, not plain text. Missing mandatory fields
(such as skattepliktig>organisasjonsnummer) give internal app errors
in the process step rather than a clear validation error.AUTH-00063 otherwise).AUTH-00004; use a distinct reference for new/extended system
users.What a Macct customer has to do
For Macct to be able to submit the VAT return, annual accounts, tax return, etc. on behalf of your company, we need one one-time approval from you:
- You get a link to Altinn (
am.ui.altinn.no) from Macct. - You log in with BankID and approve the system user request — you must have a role on the company (typically the general manager or chair of the board, or a delegated role) in Brønnøysund/Altinn.
- The approval gives Macct a system user with exactly the access packages and rights stated in the request — no more and no less.
You never share passwords, BankID codes or API keys. The authorisation is scoped, traceable, and you can withdraw it at any time in Altinn under Access management → System access. And even with the authorisation in place, Macct never submits anything unless it has been triggered and approved — submission always requires an explicit human "send".
Macct keeps the books and prepares the submissions — you approve once and press "send" when you are ready.
Try free for 30 days See the Altinn status