How do we future-proof software against Norwegian regulatory API updates?
Version the contract you depend on, and put the volatile part behind a layer that absorbs schema and endpoint changes. Concretely: read from an interface whose fields are append-only, so an existing field never changes meaning or type and never disappears without a major version bump; store the rule and schema versions alongside anything you cache; and ignore fields you do not recognise rather than rejecting them. The upstream registers will keep changing. The point is that their changes stop at a boundary you control.
What actually breaks when a government API changes?
Parsing, almost always. Connectivity failures are loud and get caught in minutes; a field renamed from one release to the next is quiet. Your request succeeds, your deserialiser produces an object with a null where a value used to be, and something three layers downstream renders an empty string or skips a rule. The first person to notice is a customer, and the gap between the change and the report is however long it takes somebody to look closely.
The variants are predictable once you have seen them. A field changes type, so a number arrives as a string. A single object becomes an array because the upstream discovered a case with two of them. An enum gains a value and your exhaustive switch falls through to a default that was written as a formality. A nested structure gets one level deeper. None of these are exotic, and all of them are survivable if the mapping lives in one place.
The second category is endpoints moving rather than fields, and it is rarer but larger. The decommissioning of Altinn 2 in June 2026 is the recent example: not a field rename but an entire platform ceasing to answer. An application that talks to a normalising layer experienced that as somebody else's migration. An application with the endpoint literal spread through its codebase experienced it as a project.
How does versioning protect application code?
Through one rule that is stronger than it sounds: the response contract is append-only. An existing field cannot change its semantics, cannot change its type, and cannot be removed without a major version bump. New fields can be added at any time. So a client written against today's response keeps working as the API grows, and the only thing it has to do in return is tolerate fields it does not recognise instead of rejecting them.
The machine-facing surfaces carry that guarantee explicitly. Each one exposes a schema_version, and a breaking change requires bumping it, so a client can assert on the version rather than discovering a change by failing. Every response envelope also carries the rule version it was evaluated under. Store both alongside anything you cache: a cached answer with its versions is re-derivable, and one without them is a number with no provenance.
On your own side, keep the wire format out of your domain model. Parse into your own types at one boundary and let the rest of your application depend on those. That way an upstream change is a diff in one file rather than a search across your codebase, and you can test the mapping in isolation without standing up the whole stack.
How do I find out about a change before it breaks production?
Watch the change archive instead of diffing records yourself. GET /api/v1/changesreturns detected changes across registry and policy sources, filterable by source, entity type, entity, change type and date, and each row carries the field path that moved along with the before and after values. That turns “something about this company is different” into a pointer at exactly what, which is the difference between a re-evaluation and an investigation.
If polling is the wrong shape for you, webhook subscriptions deliver the same deltas over signed HTTPS on the Professional tier, with retries and an HMAC signature you verify on receipt. Either way, the pattern is the same: react to a named change rather than re-evaluating your whole customer base on a timer because you cannot tell what moved.
For operational state rather than data changes, the zero-auth capability endpoint is the authoritative machine-readable source: it returns a status of live, gated or dry-run per capability. The capability status page is the human-readable equivalent and says openly that it can lag the API, so if the two disagree, believe the endpoint.
Make the first call
The first request needs no key and tells you what is live right now. The second needs the read:changes scope and tells you what has moved since a date you choose.
# Zero-auth: the authoritative machine-readable capability state.
curl -s https://www.apier.no/api/v1/capabilities// What moved, and where. Requires the read:changes scope.
const url = new URL("https://www.apier.no/api/v1/changes");
url.searchParams.set("source", "brreg");
url.searchParams.set("from", "2026-07-01");
const res = await fetch(url, {
headers: { Authorization: `Bearer ${process.env.APIER_API_KEY}` },
});
const { data } = await res.json();
for (const row of data.data) {
// field_path is the pointer to what actually moved.
console.log(row.detected_at, row.entity_id, row.field_path);
}Frequently asked questions
- What actually breaks when a Norwegian government API changes?
- Usually parsing, not connectivity. A renamed or re-typed field, a nested object that becomes an array, an enum that gains a value your switch statement does not handle. These fail quietly at the edges of your code rather than loudly at the request layer, which is why they tend to be found by a customer rather than by a monitor.
- How does versioning actually protect me?
- By making the contract append-only. An existing field cannot change meaning or type, and cannot be removed, without a major version bump. New fields can appear at any time. That single rule means a client written today keeps working as the API grows, provided it ignores fields it does not recognise rather than rejecting them.
- What should I store alongside a cached answer?
- The rulebook version and the schema version from the response envelope. Both are on _meta. With them, a cached answer is re-derivable and a version change is a signal to re-evaluate. Without them you have a value with no provenance, which is fine until someone asks why it differs from what the API says today.
- How do I find out about a change before production does?
- Poll the change archive rather than diffing whole records yourself. It returns rows filterable by source, entity and date, and each row carries the field path that moved plus the before and after values. On the Professional tier you can subscribe to webhook deliveries instead of polling.
- Should I write my own adapter layer if I use a broker?
- A thin one, yes. A broker absorbs upstream government changes, but your own application still benefits from a boundary between the wire format and your domain model. It keeps the blast radius of any change, from any provider including this one, inside a layer you can test in isolation.