Skip to content
Apier

How do accounting and bookkeeping platforms integrate with Altinn and Norwegian public registers?

With one integration and many delegations. The platform holds a single credential chain and a single client library; each client company separately grants that registered system the right to act on its behalf. From there the loop per client is the same three calls: check the delegation, look up that company's obligations and deadlines, and file through Altinn when the time comes. The engineering work scales with the number of registers you touch. The operational work scales with your customer base.

Your platform, described as one integration and one key, connects to Apier, described as one credential chain. From there a shared line fans out to three client company boxes, each of which grants its own delegation. A note underneath reads: and one more for every customer you onboard.Your platformone integration, one keyApierone credential chainClient companygrants its own delegationClient companygrants its own delegationClient companygrants its own delegationand one more for every customer you onboard
The left half is built once. The right half repeats per customer, which is why the delegation flow deserves as much product attention as the integration itself.

How do I handle hundreds of client delegations?

Treat delegation state as something you read, not something you store. The temptation at scale is to cache a connected flag per client and trust it, because checking on every action feels expensive. The flag will be wrong. Clients narrow and withdraw access without telling their software vendor, usually as a side effect of tidying up rather than as a decision about you, and your cache has no way to learn about it.

The authority check is designed for that use. It answers HTTP 200 with a verdict of full, partial or none for one organisation, together with the scopes that are live, the ones that are missing, and fix steps written in Norwegian to be shown to the client. Because a not-yet-authorised state is a normal response rather than an error, you can branch on it in ordinary product code instead of parsing failures.

At scale the useful design is a per-client status you refresh on a schedule and re-check before any action that depends on it. Surface the fix steps in your own interface rather than a generic disconnected message: the client can usually resolve it themselves in a few minutes if you tell them what to click, and a support ticket costs you both more than that.

How do I surface each client's deadlines in my own product?

Query the per-company deadline endpoint with a from_date and a horizon_months, once per client on a schedule, and render what comes back. A twelve-month horizon refreshed nightly is usually the right shape: it is enough to drive a calendar view and a notification queue, and it is cheap enough to run across a large book without special handling.

Read adjusted_from before you display anything. When it is not null, the statutory date moved because it fell on a weekend or a Norwegian public holiday, and showing both dates prevents the conversation where an accountant who knows the rule is certain your product is wrong. The response also carries the entity types each entry applies to, so filtering to what a given client actually owes is a field comparison rather than logic you maintain.

For the wider picture of how this fits an accounting platform specifically, including where the per-client work sits in an onboarding flow, see the accounting software use case.

What changes when a client's registry data changes?

Their obligation set can change with it, which is the part that catches platforms out. A company that registers for VAT gains VAT reporting from that point. A change of legal form changes which annual filings apply. A company entering dissolution changes what is expected of it. None of these arrive as a message from the client; they arrive as a difference in the registry that your product has no reason to notice.

So watch the change archive rather than re-evaluating everything on a timer. It returns detected changes filterable by source, entity and date, and each row carries the field path that moved along with the before and after values, so you can re-evaluate the named clients and leave the rest alone. On the Professional tier the same deltas can be delivered as signed webhooks if polling is the wrong shape for your architecture.

One habit is worth building in from the start. Store the rule version and the correlation id from any evaluation you show a client. When somebody asks in eight months why the platform said a deadline was on a particular date, those two fields turn the answer from a reconstruction into a lookup.

Make the first call

The sandbox call shows the per-client deadline shape before you have onboarded anyone. The TypeScript snippet is the per-client authority check, written as the branch it should be rather than as an error path.

# Zero-auth sandbox: the per-client shape, before any onboarding.
curl -s https://www.apier.no/api/v1/sandbox/public/company/999999999/deadlines
// Per-client authority check. Always HTTP 200.
async function clientState(orgNumber: string) {
  const res = await fetch(
    `https://www.apier.no/api/v1/auth/permissions/${orgNumber}`,
    { headers: { Authorization: `Bearer ${process.env.APIER_API_KEY}` } },
  );

  const { data } = await res.json();
  // "full" | "partial" | "none". A product state, not an error.
  return { status: data.status, fixSteps: data.fix_steps };
}

Frequently asked questions

Do I need one integration per client company?
No. You build one integration and hold one credential chain. What repeats per client is the delegation: each company grants your registered system access to act on its behalf. So the engineering work is bounded by the number of registers you touch, while the operational work scales with your customer base.
How do I track delegation state across hundreds of clients?
Ask rather than cache. GET /api/v1/auth/permissions/{org} answers HTTP 200 with a verdict of full, partial or none for one organisation, plus the scopes that are missing and Norwegian fix steps you can put straight in front of the client. Storing a connected flag in your own database is a claim about the past, and it will be wrong the first time a client tidies their access list.
Can I see which of my own principals hold authority for a client?
Yes. The fullmakt endpoint answers, for one customer organisation, which of your own agent principals currently hold delegated authority, which scopes are live and which are missing relative to your tier. It is the read side of the request flow, and it is the right call to make before an agent attempts an action rather than after it fails.
How do I show each client's deadlines in my own interface?
Query the per-company deadline endpoint with a from date and a horizon in months, once per client on a schedule, and render the result. Read adjusted_from before you display a date: when it is not null, the statutory date moved for a weekend or a holiday, and showing both prevents the support conversation where a client insists your date is wrong.
What happens when a client's registry data changes?
Their obligation set can change with it. A company that registers for VAT gains VAT reporting; a change of legal form changes what applies. Poll the change archive for the sources and entities you care about, or subscribe to webhook deliveries on the Professional tier, and re-evaluate the clients it names rather than sweeping your whole book on a timer.