Why does my Maskinporten API delegation return 403?
Because somewhere in the chain, someone lacks a right they are trying to pass on. An organisation can only delegate an API it has itself been granted, the person performing the delegation must hold the authority to delegate that specific API, and the scope must have been made delegable by its provider in the first place. The delegator's own rights are the ceiling: nothing below them in the chain can hold more. Most delegation 403s resolve to one of those three conditions, plus two timing traps, a grant made in Altinn 2 that does not resolve in Altinn 3, and a fresh portal grant the API cannot see yet.
Who must hold what before a delegation can succeed?
The model has three parties and a strict order. The API provider grants a Maskinporten scope to its consumer organisations, and the provider never grants the supplier directly. A customer that holds the access can then delegate it onward to a supplier through Altinn, and the supplier's client requests tokens that name the customer organisation, receiving a token that carries both identities. Every hop is a real authorisation decision, which is why the failure can sit at any of them.
Two conditions must hold before the delegating person even reaches the screen. The scope must be delegable at all: a Maskinporten scope without a delegation source cannot use Altinn for delegation, full stop, and enabling that is the provider's registration work, not the customer's. And the resource behind the scope carries a policy deciding who may delegate it, so the person acting for the customer must hold a role that policy accepts. The portal flow is documented as a key role holder's job, typically the general manager.
That is the ceiling rule. A supplier cannot receive more than the customer holds, the customer cannot delegate more than the provider granted, and the person clicking delegate cannot pass on rights outside their own role. When a delegation fails, walk the chain left to right and ask at each step whether this party holds what the next one needs.
Why is the delegation request rejected at the authorization step?
The symptom integrators report looks like this: a POST of a maskinportenschema delegation, with the delegating organisation's number in the header, answered with an authorisation rejection before anything is created. The request is well formed, the organisation exists, and the response still says no. That shape means the policy check on the delegating side failed, not that the payload was wrong, so re-validating the request body is time spent in the wrong place.
What makes this failure expensive is that the surfaced error says access is denied without naming the missing role. The person holds a senior title, the organisation clearly uses the API, and nothing in the response distinguishes a missing role from a missing grant from a non-delegable scope. Integrators observe exactly this opacity, and it turns a rights question into what looks like a platform fault.
Debug it as a rights question anyway, in ceiling order. First confirm the scope is delegable, because if the provider never set a delegation source, no person can succeed. Then confirm the customer actually holds the access being passed on. Then have the delegation performed by someone the resource policy accepts, which in the portal flow means a key role holder. Three checks find the failing hop instead of a support ticket.
| Symptom | Likely cause | Fix |
|---|---|---|
| maskinportenschema POST rejected (observed) | The policy check on the delegating organisation fails: the acting person lacks a role the resource policy accepts. | Have a key role holder, typically the general manager, perform or approve the delegation. |
| Access denied with no role named (observed) | The rejection does not distinguish a missing role from a missing grant or a non-delegable scope. | Walk the chain in order: scope delegable, customer holds access, person holds the role. |
| Scope cannot be delegated at all | The provider has not set a delegation source, so Altinn delegation is unavailable for that scope. | Ask the API provider to enable delegation; no customer-side role can work around this. |
| Altinn 2 grant not resolving in Altinn 3 (observed) | Some grants lapse across the platform boundary and are documented as needing re-delegation. | Re-delegate under the new model; after Altinn 2 closes, only the new access packages can be delegated. |
| Portal grant not visible to the API yet (observed) | A window between the portal recording the grant and the API surface evaluating it. | Verify the target organisation number, wait, and re-check before treating the grant as failed. |
| Supplier client set up on behalf of a customer | The supplier's integration filled the on-behalf-of-a-customer field, which this flow does not use. | Register the integration on the supplier's own organisation and add the provider's scope to it. |
Why do Altinn 2 grants and fresh portal grants not show up?
The era boundary is the structural one. Delegations made in Altinn 2 do not reliably resolve for the recipient in Altinn 3 flows, and for some grants that is documented rather than accidental: Skatteetaten's transition guidance names old grants that lapse and must be delegated anew, and once Altinn 2 closes, only the new access packages can be delegated. If a customer insists they granted access years ago and your integration cannot see it, believe both of you, and re-delegate under the new model.
The propagation trap is smaller but sharper. Integrators observe that a delegation which succeeded in the portal can take time to become visible to the API that evaluates it, so the first authorisation check after a grant can fail even though nothing is wrong. Build for it: confirm the delegation named the right supplier organisation number, then re-check on a delay before concluding the grant failed, and keep the retry bounded so a real failure still surfaces.
Which packages replaced which Altinn 2 roles, and why the new model delegates bundles rather than single rights, is owned by the role mapping guide. And if your failures sit around a systembruker request rather than an organisation-to-organisation scope delegation, the system user troubleshooting guide walks that cluster symptom by symptom.
How do I see the missing right instead of a bare 403?
The upstream rejection is not going to start naming roles for you, so stop relying on it. Ask the authority question separately, before the call that needs it, and treat a missing right as a state your product displays rather than an exception it catches. Each hop in the chain becomes something you read.
That is what Apier's fullmakt surface does. The status endpoint returns the delegation state for a company as data: an overall verdict of full, partial or none, the scopes that are active, the ones that are missing per principal, and Norwegian fix steps you can hand to the customer, naming what to grant and where. A delegation that would have failed downstream as an unexplained 403 shows up here as a named gap with an owner.
Make the first call
The sandbox call answers who may act for a company at all, with no key. The TypeScript sample reads the delegation state for one company, with the missing scopes and fix steps in the body instead of in a rejection.
# Zero-auth sandbox: who may act for a company, from the registry.
curl -s https://www.apier.no/api/v1/sandbox/public/company/999999999/authority// The authority state as something you read: active scopes, missing
// scopes and Norwegian fix steps, instead of a bare 403 downstream.
const res = await fetch("https://www.apier.no/api/v1/fullmakt/999999999", {
headers: { Authorization: `Bearer ${process.env.APIER_API_KEY}` },
});
if (!res.ok) {
// Every non-2xx answers the same structured envelope.
const { error_code, explanation } = await res.json();
throw new Error(`${error_code}: ${explanation.summary}`);
}
const { data } = await res.json();
// "full" | "partial" | "none", with the gap named per principal.
for (const p of data.principals) {
console.log(p.display_name, p.delegation_status, p.missing_scopes);
}
console.log(data.overall_status, data.fix_steps);Frequently asked questions
- Who can delegate an API scope to a supplier?
- Someone at the customer organisation whose own authority covers the API being delegated. The portal flow is performed by a key role holder, typically the general manager, and the resource behind the scope carries a policy that decides who may delegate it. A person cannot pass on an access their organisation does not hold, and cannot delegate past the limits of their own role.
- Why is the scope not delegable at all?
- Because the API provider has not enabled delegation for it. A Maskinporten scope can only be delegated through Altinn when the provider has set a delegation source for it and registered a matching delegable resource. If that setup does not exist, no role and no amount of authority at the customer will make the delegation possible; the fix sits with the provider, not with you.
- The customer delegated in the portal. Why does the API still say no?
- Integrators observe a window where a grant that is visible in the portal has not yet reached the API surface that evaluates it. Before escalating, confirm the delegation targets the right supplier organisation number, then re-check after a delay rather than assuming the grant failed. If the gap persists, treat it as an incident rather than a rights problem.
- Do delegations made in Altinn 2 carry over to Altinn 3?
- Not reliably, and some are documented to lapse. Skatteetaten's transition guidance names grants that expire across the boundary and must be delegated anew, and once Altinn 2 closes, only the new access packages can be delegated. When a recipient cannot see an old grant in an Altinn 3 flow, re-delegating under the new model is the fix to try first.
- How does Apier surface the missing right instead of a bare 403?
- By separating the question of authority from the call that needs it. The fullmakt endpoints return the delegation state as data: an overall status of full, partial or none, the scopes that are active, the ones that are missing, and Norwegian fix steps written to be shown to the customer. Your integration reads who lacks what before acting, instead of discovering it as an unexplained rejection.