Hopp til innhold

Kan en AI-agent spørre mot og samhandle med Altinn-API-er?

Spørre og validere, ja, mot reelle data, i dag. Bindende innsending, nei. En agent kan lese et selskaps registerfakta, plikter, frister, signaturrett og innsendingshistorikk, og den kan tørrkjøre en nyttelast mot det reelle regelsettet og få tilbake en avgjørelse per sjekk. Det den ennå ikke kan, er å legge en innsending inn i et offentlig system: den veien går mot en sandkasse og en mock-adapter, og godkjenningene som ville gjort den reell er utestående. Denne siden sier det rett ut fordi det er dyrt å oppdage det motsatte sent.

En AI-agent kobles til tre steg etter hverandre. Lese, beskrevet som live mot reelle registerdata. Validere, beskrevet som tørrkjøring uten bivirkninger. Sende inn, beskrevet som sandkasse eller styrt. En stiplet loddrett linje står foran innsendingssteget, merket: ingen live offentlig skriving forbi denne linjen.AI-agentLeselive, reelle registerdataValideretørrkjøring, ingen effektSende innsandkasse eller styrtingen live offentlig skriving forbi denne linjen
De to første stegene svarer mot produksjonsdata. Den stiplede linjen er der det ærlige svaret endrer seg, og alt til høyre for den er enten syntetisk eller venter på en godkjenning.

Hva kan en agent gjøre i dag, og hva er styrt?

Leseflaten er live og svarer mot reelle registerdata. En agent kan slå opp et selskap fra et navn, hente konteksten, spørre hva det må sende inn og når de neste fristene faller, finne ut hvem som har signaturrett, og lese innsendingshistorikken. Dette er vanlige autentiserte kall, de returnerer et normalisert skjema på tvers av kilder, og hvert svar bærer regelversjonen og datafriskheten det ble produsert under.

Validering er også live, med en snevrere betydning enn det høres ut som. Å kalle utførelsesendepunktet med dry_run=true kjører en reell nyttelast for et reelt selskap gjennom regelmotoren og rapporterer hver sjekk for seg. Det gir ingen bivirkning oppstrøms, og det er derfor det er styrt av et scope med lese-prefiks til tross for at det ligger på en skrive-formet sti. Et 200-svar som bærer all_passed: false er suksesstilfellet: tørrkjøringen kjørte, og avgjørelsene ligger i kroppen.

Bindende innsending er den styrte. To eksterne godkjenninger står foran den, en Maskinporten-produksjonsklient og en Altinn-scopegodkjenning, og ingen av dem har landet. Til de gjør det, kjører legitimasjonsadapterne i mock-modus, så et utførelseskall som ikke er en tørrkjøring løses opp gjennom en deterministisk mock framfor et offentlig endepunkt. Én handlingstype er ikke koblet for live innsending i det hele tatt og svarer med et uttrykkelig avslag framfor en falsk suksess, som er oppførselen du vil ha fra noe så konsekvensrikt.

Hva en AI-agent kan gjøre mot Altinn gjennom Apier akkurat nå, per operasjon, med gjeldende driftstilstand for hver.
OperasjonTilstand i dagHva det betyr i praksis
Lese selskapsdataLive, mot reelle registerdata.Kontekst, plikter, frister, signaturrett og innsendingshistorikk svarer normalt med en API-nøkkel.
Validere en innsending (tørrkjøring)Live, og bare validering.En reell nyttelast sjekkes mot det reelle regelsettet og hver sjekk rapporteres. Ingenting sendes inn og ingen oppstrømskilde kalles.
Sende inn gjennom sandkassenLive, og syntetisk.En lokal tilstandsendring mot testdata. Deterministisk, testbar, og den når aldri Altinn, Maskinporten eller Skatteetaten.
Sende inn på ekte (bindende)Styrt.Venter på en Maskinporten-produksjonsklient og en Altinn-scopegodkjenning. Til begge lander, forlater ingen innsending systemet.
Godkjenne en bindende handlingReservert, kan ikke tildeles.Godkjenningsscopet kan ikke gis til en API-nøkkel, så en agent kan ikke utløse sin egen bindende handling selv i prinsippet.

Hvordan skiller en tørrkjøring seg fra en innsending?

En tørrkjøring svarer på «ville dette blitt godtatt». Den tar den samme forespørselskroppen en innsending ville tatt, for samme selskap og periode, og kjører den gjennom sjekkene: om dataformatet er riktig, om plikten gjelder, om delegeringen som dekker den er på plass, om perioden er en du fortsatt kan sende inn for. Hver sjekk kommer tilbake for seg, så en feil forteller deg hvilken betingelse som ikke er oppfylt framfor at noe gikk galt.

En innsending svarer på «gjør det», og forskjellen er ikke så mye et flagg på samme operasjon som en annen risikoprofil. Innsending er idempotensnøklet, fordi en gjentatt innsending som sender to ganger er et vesentlig verre utfall enn en som feiler én gang. Kontrakten dens sier at den bruker opp et engangs godkjenningstoken, men håndhevingen som setter en ugodkjent skriving på vent leveres avslått i dag (se neste avsnitt). Og den er den eneste av de to som noen gang kan gi en konsekvens utenfor ditt eget system, som er nettopp derfor den fortsatt står bak en sperre.

For agentdesign er den nyttige følgen at tørrkjøringen er trygg å kalle spekulativt og innsendingen ikke er det. En agent som validerer før den foreslår, gir brukeren noe konkret å godkjenne. Gjennomgangen av MVA-innsending i dokumentasjonen kjører hele sekvensen fra ende til ende, fra oppdagelse av plikten gjennom validering til den styrte innsendingskontrakten.

Hvordan holder man et menneske i sløyfen på en bindende innsending?

Ved å gjøre godkjenning til en legitimasjon agenten ikke kan ha. Scopet som utløser en bindende handling ligger i et reservert prefiks som ikke kan tildeles noen API-nøkkel, og mellomvaren avviser det uansett hva nøkkelen ellers bærer. Det er et strukturelt svar framfor et retningslinjesvar: det finnes ingen konfigurasjon der en agents egen nøkkel godkjenner agentens egen innsending, så spørsmålet om du stolte riktig på den oppstår aldri.

På toppen av det finnes en suspensjonsmekanisme. Når den er slått på, blir en bindende skriving som kommer uten godkjenningstoken satt på vent framfor utført, og kalleren får tilbake en ventende handling med en godkjenningslenke bygget fra serverkonfigurasjon framfor fra den innkommende forespørselen. Den siste detaljen betyr mer enn den ser ut til: å bygge lenken fra en forespørselsheader ville latt en angriper peke godkjenningsskjermen dit vedkommende ville.

Mekanismen leveres avslått, og gitt at bindende innsending selv er styrt, er det den sammenhengende standarden framfor en forglemmelse. Det betyr for deg at formen på menneske-i-sløyfen allerede er bestemt, og at du kan bygge produktflyten din rundt den nå: agenten forbereder og validerer, en person godkjenner, godkjenningen brukes opp nøyaktig én gang. Bare det siste steget venter på noen andres godkjenningsprosess.

Gjør det første kallet

Det første kallet trenger ingen nøkkel og sender ingenting: det planlegger en MVA-melding mot sandkassen. Det andre er tørrkjøringen mot reelle regler, og feltet du leser først er outcome.all_passed.

# Nøkkelløs sandkasse: planlegg en MVA-melding uten å sende noe.
curl -s https://www.apier.no/api/v1/sandbox/public/actions/plan \
  -H "content-type: application/json" \
  -d '{"org_number":"999999999","action":"mva_melding"}'
// Tørrkjøring mot det reelle regelsettet. Ingen bivirkninger.
const res = await fetch(
  "https://www.apier.no/api/v1/actions/execute?dry_run=true",
  {
    method: "POST",
    headers: {
      "content-type": "application/json",
      Authorization: `Bearer ${process.env.APIER_API_KEY}`,
    },
    body: JSON.stringify({
      org_number: "999999999",
      action_type: "mva_melding",
      period: "2026-T1",
      payload: {},
    }),
  },
);

// 200 med all_passed: false er SUKSESS-stien. Feilede sjekker er
// innhold, ikke transport: tørrkjøringen kjørte og rapporterte.
const { data } = await res.json();
console.log(data.outcome.all_passed, data.outcome.checks);

Ofte stilte spørsmål

Kan en AI-agent sende inn et skjema til Altinn i dag?
Ikke som en bindende offentlig innsending. Kallformen finnes og sandkassen tar imot den, men live innsending er styrt bak en Maskinporten-produksjonsklient og en Altinn-scopegodkjenning som ikke er på plass ennå. Lesing og validering er live mot reelle data. Behandle innsending som en kontrakt du kan bygge mot framfor en evne du kan lansere på.
Hva får en agent ut av en innsending i sandkassen da?
Bevis på at kodeveien din er riktig. Sandkassen svarer med produksjonens responsform fra syntetiske testdata, deterministisk, så du kan asserte på den i en testsuite, og den kan injisere feiltilfeller på forespørsel slik at feilhåndteringen din blir prøvd. Det den ikke kan gi deg er noe bevis om en reell innsending, fordi sandkassen aldri kaller et offentlig system på noen verb.
Hvordan skiller en tørrkjøring seg fra et sandkassekall?
En tørrkjøring vurderer en reell nyttelast for et reelt selskap mot det reelle regelsettet og rapporterer hvilke sjekker som gikk gjennom. Et sandkassekall kjører mot syntetiske testdata for et reservert testorganisasjonsnummer. Tørrkjøringen sier om denne innsendingen ville blitt godtatt; sandkassen sier om klienten din er riktig koblet. Begge stopper før innsending.
Kan en agent godkjenne sin egen innsending?
Nei, og det er håndhevet framfor bare anbefalt. Godkjenningsscopet ligger i et reservert prefiks som ikke kan tildeles noen API-nøkkel, så en nøkkel som viser til det blir avvist uansett hva den ellers har. En agent kan forberede og validere en bindende handling; en egen menneskelig beslutning kreves for å utløse den.
Hvordan vet jeg hvilken funksjonalitet som er live akkurat nå?
To kilder, og de er enige av konstruksjon. GET /api/v1/capabilities returnerer et maskinlesbart status-felt med live, gated eller dry-run på hver funksjon, og det er den å lese hvis du er en maskin. Statussiden for funksjonalitet i dokumentasjonen er den menneskelesbare ekvivalenten og sier uttrykkelig at den kan henge etter API-et.