Hvordan gjør jeg mitt første BRREG-API-kall steg for steg?
Av Antony Richard Grov, gründer av Apier
Fem steg, hvert på en kommando eller mindre. Først velger du et organisasjonsnummer og sjekker formen: ni sifre med et MOD-11-kontrollsiffer, med 999999999 som plassholder i alle eksemplene her. Deretter kaller du det nøkkelløse sandkassespeilet på /api/v1/sandbox/public/company/999999999/summary; det krever ingen nøkkel og svarer med en produksjonsformet konvolutt. Så leser du det som kom tilbake: et suksessflagg, en datablokk med normaliserte registerfelter, og en _meta-blokk som merker svaret som simulert med is_sandbox satt til true. Deretter oppretter du en API-nøkkel og kaller den levende ruten med en Authorization: Bearer-header. Til slutt lærer du de få feilene hver første integrasjon møter, fra feilet sjekksum til manglende header, så hver av dem kommer merket i stedet for mystisk.
Steg 1: hvilket organisasjonsnummer starter jeg med?
Hvert norsk selskapsoppslag nøkles på organisasjonsnummeret, den 9-sifrede identifikatoren Brønnøysund tildeler ved registrering. Det niende sifferet er et MOD-11-kontrollsiffer beregnet fra de åtte første, som betyr at nummeret bærer sin egen skrivefeildetektor. Valider formen før noe treffer nettet: nøyaktig ni sifre, bestått sjekksum. Plassholderen i dokumentasjonen er 999999999, og det er nummeret denne veiledningen bruker hele veien.
Hold de to feiltypene fra hverandre fra starten, for de trenger ulike løsninger. Et nummer som stryker på sjekksummen, ble feilskrevet eller ødelagt et sted mellom kilden og koden din, og ingen API-kall kan reparere det; rett sifrene i stedet. Et nummer som består sjekksummen, men mangler i registeret, er et annet problem, et eksistensspørsmål snarere enn et formspørsmål, og det dukker opp senere som et ikke-funnet-svar.
Starter du fra et selskapsnavn i stedet for et nummer, slå det opp først i stedet for å konstruere noe: veiledningen om oppslag av organisasjonsnummer dekker navnesøk fra ende til ende. En påfunnet verdi som tilfeldigvis består MOD-11, kan tilhøre et helt annet selskap, som er et verre utfall enn en feil.
Steg 2: hvordan gjør jeg det første kallet uten nøkkel?
Pek curl mot sandkassespeilet: GET /api/v1/sandbox/public/company/999999999/summary på https://www.apier.no. Flaten er nøkkelløs med vilje, så det er ingen registrering, ingen token og ingen header å sette sammen; kommandoen nederst på denne siden er hele forespørselen. Det som svarer, er simulerte data formet nøyaktig som den levende rutens svar, og det gjør speilet til det tryggeste stedet å lære konvolutten.
Konvolutten har tre deler. Et success-flagg forteller med et blikk om kallet lyktes. data-blokken bærer selskapsfaktaene: org_number, entity_type, data_tier, en obligations-liste, en deadlines-kalender og en upgrade_path-peker. _meta-blokken bærer opphavet: is_sandbox satt til true, en sandbox_notice som sier at dette er Apiers interne mock, pluss data_freshness, source og en rulebook_version med verdien sandbox.
En ærlighetsdetalj er verdt å kjenne før du eksperimenterer: det offentlige speilet serverer bare fikstur-selskapet 999999999. En misformet stiverdi svarer 400 med VALIDATION_FAILED, og et velformet 9-sifret nummer som ikke er fiksturen, avvises med en eksplisitt kode i stedet for å late som selskapet finnes. Simulerte data utgir seg aldri for å være et ekte oppslag.
Steg 3: hva fikk jeg egentlig tilbake?
Normaliserte registerfelter, ikke den rå Enhetsregisteret-nyttelasten. Brønnøysunds egne REST-svar bruker registerets feltnavn og nesting som du ellers måtte kartlagt inn i din egen modell for hånd; sammendraget svarer i stedet med et stabilt, allerede normalisert selskapsobjekt, med samme navn på tvers av hvert oppstrøms register. Parsingkoden din binder seg til den ene formen, og kartleggingsarbeidet blir på API-siden av grensen.
Den dype felthistorien, hvilke registre som finnes bak flaten, hva det åpne laget inneholder og ikke, og hvordan ferskhet og endringsdeteksjon fungerer, gjentas bevisst ikke her: veiledningen om tilgang til Brønnøysund-data eier den. For denne veiledningen holder det at feltene du nettopp leste, er de samme du leser i produksjon.
Steg 4 og 5: hvordan går jeg live, og hvilke feil kommer først?
Å gå live er en header og en stiendring. Opprett en API-nøkkel i dashbordet, hold den i en miljøvariabel som process.env.APIER_API_KEY, og send den som Authorization: Bearer på GET /api/v1/company/999999999/summary. Konvolutten beholder formen; innholdet kommer nå fra det virkelige registeret, og _meta oppgir ferskhet og kilde i stedet for sandkassemarkørene. Hva statusfeltene betyr for et selskap du er i ferd med å stole på, dekkes av veiledningen om verifisering av selskapsstatus.
Feil følger samme disiplin som suksesser. Hvert ikke-2xx-svar er den samme strukturerte konvolutten: en maskinlesbar error_code pluss en explanation-blokk med oppsummering og løsningssteg, aldri en naken statuskode eller en HTML-side. Det betyr at feilhåndteringen din er en eneste kodesti, og tabellen under er et kart over kodene en første integrasjon faktisk møter, omtrent i den rekkefølgen den møter dem.
Den ene oppføringen som kan prøves igjen, er ratebegrensningen. En 429 kommer med en Retry-After-header som oppgir hvor mange sekunder du skal vente, og riktig respons er å vente nøyaktig så lenge i stedet for å hamre. Alt annet i tabellen kan ikke løses ved gjentakelse: en identisk forespørsel feiler identisk, så løsningen ligger alltid i input eller header, aldri i å prøve på nytt.
| Feil | Hva den betyr | Hva du gjør |
|---|---|---|
| 400 VALIDATION_FAILED | Organisasjonsnummeret er ikke 9 sifre, eller et annet felt strøk på formvalideringen. | Rett feltet som navngis i explanation.details; samme forespørsel feiler identisk. |
| Sjekksumfeil | 9 sifre, men MOD-11-kontrollsifferet stemmer ikke: en skrivefeil, ikke et manglende selskap. | Kontroller sifrene mot kilden din; profilruten avviser det tidlig som ORG_NUMBER_INVALID_CHECKSUM. |
| 404 NOT_FOUND / COMPANY_NOT_FOUND | Et velformet nummer som Enhetsregisteret ikke holder: avregistrert, aldri registrert, eller feil. | Verifiser nummeret, eller slå det opp fra selskapsnavnet; ikke prøv igjen. |
| 401 AUTH_MISSING | Authorization: Bearer-headeren mangler eller er misformet på en levende rute. | Send en gyldig API-nøkkel i headeren; å prøve igjen uten feiler identisk. |
| 429 RATE_LIMIT_EXCEEDED | For mange forespørsler i gjeldende vindu for nøkkelen eller IP-en din. | Vent antall sekunder i Retry-After-headeren, og prøv så igjen; ro ned, ikke hamre. |
Gjør det første kallet
Hele veien i to kommandoer. Curl-linjen er steg to: det nøkkelløse sandkassesammendraget, simulert og merket som det. TypeScript-eksempelet er steg fire: samme sammendrag fra det levende registeret, med nøkkelen i headeren og samme konvolutt på begge sider.
# Steg 2 i en kommando: nøkkelløs sandkasse, simulert men produksjonsformet.
curl -s https://www.apier.no/api/v1/sandbox/public/company/999999999/summary// Steg 4 i en forespørsel: samme sammendrag, nå live, med en nøkkel.
const res = await fetch(
"https://www.apier.no/api/v1/company/999999999/summary",
{ headers: { Authorization: `Bearer ${process.env.APIER_API_KEY}` } },
);
if (!res.ok) {
// Alle ikke-2xx-svar bruker den samme strukturerte konvolutten.
const { error_code, explanation } = await res.json();
throw new Error(`${error_code}: ${explanation.summary}`);
}
const { data, _meta } = await res.json();
// is_sandbox er borte her; ferskhet og versjon oppgis i stedet.
console.log(data.org_number, data.entity_type, _meta.data_freshness);Ofte stilte spørsmål
- Trenger jeg API-nøkkel for det første kallet?
- Nei. Sandkassespeilet under /api/v1/sandbox/public er nøkkelløst med vilje, så den aller første forespørselen er en enkelt curl-kommando uten registrering foran. Det serverer fikstur-selskapet 999999999 og svarer med samme konvoluttform som den levende ruten. Nøkkelen kommer først inn i steg fire, når du vil ha ekte registerdata i stedet for den simulerte fiksturen, og den sendes i en helt vanlig Authorization: Bearer-header.
- Er sandkassedataene ekte?
- Nei, og svaret sier det selv. Hvert sandkassesvar bærer _meta.is_sandbox satt til true pluss en sandbox_notice-streng som sier at dette er Apiers interne mock, ikke et offentlig testmiljø. Formen er derimot den samme som på den levende ruten: samme suksessflagg, samme datafelter, samme _meta-struktur. Det er hele poenget med speilet: du skriver parsingkoden en gang mot simulerte data og beholder den uendret når du går live.
- Hvorfor svarer et gyldig formet nummer med ikke funnet?
- Fordi en bestått sjekksum bare beviser formen, ikke eksistensen. MOD-11-kontrollsifferet fanger skrivefeil, men en verdi som tilfeldigvis validerer, er ikke dermed registrert i Enhetsregisteret. Den levende sammendragsruten svarer 404 med koden NOT_FOUND for et slikt nummer, og profilruten bruker COMPANY_NOT_FOUND for samme situasjon. Ingen av dem kan løses ved å prøve igjen: verifiser nummeret mot registeret, eller slå det opp fra selskapsnavnet, i stedet for å gjenta kallet.
- Hva forteller _meta-blokken meg?
- Opphavet til svaret du nettopp fikk. Den oppgir rulebook_version som evalueringen kjørte under, data_freshness for når dataene ble hentet, last_verified for regelgjennomgangen, og kilden for svaret. På sandkassesvar bærer den i tillegg is_sandbox: true og sandbox_notice-strengen, som er slik koden og loggene dine skiller et simulert svar fra et levende uten å sammenligne URL-er.
- Hvordan går jeg fra sandkasse til live?
- Tre små endringer. Opprett en API-nøkkel i dashbordet, legg den til som en Authorization: Bearer-header, og fjern /sandbox/public-segmentet fra stien, slik at kallet blir GET /api/v1/company/999999999/summary. Konvolutten beholder formen, så ingenting i parsingen din endres; det som endres, er innholdet, som nå kommer fra det virkelige registeret, og _meta-blokken, som oppgir ferskhet og kilde i stedet for sandkassemarkørene.