Fra FSWS-BAS til FS GraphQL API
⚠ FSWS-BAS avvikles etter 31. mars 2027. Flere av operasjonene under er allerede slått av og returnerer feil i dag — se Operasjoner som allerede er avviklet. Se Sikts avviklingspraksis og avviklingsloggen. Kilde: Teknisk dokumentasjon for FSWS-BAS (REST)
Denne guiden hjelper deg migrere fra FSWS-BAS til FS GraphQL API.
BAS-tjenesten består av endepunkter laget til litt forskjellige formål:
- Oppdatering av brukernavn, e-post, bilder og fagpersoner
- Oppslag på fagpersoner, kull og steder
- Full- og inkrementell eksport av brukerdata (
basDataogbasEksport)
Under gir vi et eksempel per endepunkt. Listen er ikke komplett, og GraphQL gir større fleksibilitet enn BAS gjorde: du bestemmer selv hvilke felt som skal med, og kan hente data som i BAS krevde flere kall i én spørring. Ta kontakt med fs-support@sikt.no dersom du trenger hjelp til å finne en spørring eller mutasjon som passer ditt behov.
Før du starter
Sett deg inn i disse tingene før du går videre:
- Tilgang, endepunkt og kontraktsnivå (
Feature-Flags-header): Kom i gang - Paginering: Spørringer
- Feilhåndtering: Mutasjoner
- Autorisasjon (RAS): Tilgangsstyring med RAS
- Bruker du en integrasjonsplattform (Gravitee/IntArk): FS GraphQL API og IntArk
- Utforsk skjemaet selv: Introspeksjon
Migrerer du fra FS-APIet i samme integrasjon, finner du tilsvarende eksempler i Fra FS-APIet til FS GraphQL API.
Kontraktsnivå i eksemplene
Eksempler som krever headeren Feature-Flags: beta,experimental er merket med kontraktsnivå rett over kodeblokken. Er et eksempel ikke merket, ligger alt det bruker på stable og virker uten header.
- stable — dekket av API-kontrakten. Bygg produksjonsintegrasjoner på dette.
- beta — kan endres, men med varslingsfrist.
- experimental — kan endres eller forsvinne uten varsel. Ikke bygg produksjonsintegrasjoner på dette. Trenger du et experimental-felt i produksjon, ta kontakt med fs-support@sikt.no og be om at det løftes til beta.
Flere av BAS-feltene har i dag bare en experimental-erstatning. Det er markert eksplisitt der det gjelder, slik at du kan planlegge rundt det.
Institusjonsnummer i eksemplene
De fleste spørringene i FS GraphQL API krever at du oppgir hvilket lærested dataene tilhører. Argumentet heter eierOrganisasjonskode, og tar institusjonsnummeret til lærestedet som eier dataene — samme verdi som BAS brukte som institusjonsnr. Eksemplene under bruker eierOrganisasjonskode: "1234" — bytt ut «1234» med institusjonsnummeret til ditt lærested.
Paginering: nytt i forhold til BAS
BAS returnerte hele resultatsettet i ett XML-svar. FS GraphQL API paginerer listespørringer etter Relay-standarden: du får et Connection-objekt med edges { node } (eller kortformen nodes), pageInfo og totalCount, og henter neste side ved å sende endCursor fra forrige svar inn som after. Standard sidestørrelse er 100. Se Spørringer § Paginering for det fullstendige mønsteret.
Eksemplene under bruker små first-verdier for å holde svarene lesbare. I en reell eksport må du paginere gjennom alle sidene.
IDer: er de samme som i FSWS-BAS?
Nei. BAS identifiserer objekter med nøkler hentet rett fra FS: fødselsnummer for en person, en firedelt stedkode (institusjonsnr_faknr_instituttnr_gruppenr) for et sted, og STUDIEPROGRAMKODE_ÅRSTALL_TERMIN for et kull. FS GraphQL API bruker i stedet én ID-verdi per objekt.
Behandle disse ID-ene som ugjennomsiktige. Du kan riktignok base64-dekode dem, men innholdet og formatet er en intern implementasjonsdetalj som kan endres uten varsel — ikke konstruer dem selv, og ikke parse dem for å hente ut de gamle nøklene. Bruk dem kun slik du fikk dem.
FS GraphQL API skiller mellom personprofilen (grunndataene om personen ved ett lærested — navn, fødselsnummer, e-post, Feide-bruker) og rollene personen har der: StudentVedLarested og FagpersonVedLarested. BAS blandet disse i ett objekt. Hver av dem har sin egen ID, og mutasjonene under tar den ene eller den andre — sjekk hvilken før du sender inn.
Har du en BAS-nøkkel og trenger tilsvarende GraphQL-ID, bruker du en oppslagsspørring:
| BAS-nøkkel | Oppslagsspørring | Kontraktsnivå |
|---|---|---|
| Fødselsnummer → personprofil | personProfilerGittFodselsnumre | stable |
| Fødselsnummer → student | studenter med fodselsnumre-filter | stable |
| Fødselsnummer → fagperson | fagpersoner med fodselsnumre-filter | stable |
| Feide-brukernavn → personprofil | personProfilerGittFeideBrukere | stable |
| Stedkode (4-delt) → organisasjonsenhet | organisasjonsenheterGittOrganisasjonsenhetskoder | stable |
| Studieprogramkode + årstall + termin → kull | kullGittLegacyIder | experimental |
Eksempel — fra fødselsnummer til personprofil-ID, som du trenger for mutasjonene under:
query PersonProfilId {
personProfilerGittFodselsnumre(
eierOrganisasjonskode: "1234"
fodselsnumre: ["XXXXXXXXXXX"]
) {
id
navn {
fornavn
etternavn
}
}
}
Eksempel på svar:
{
"data": {
"personProfilerGittFodselsnumre": [
{
"id": "NzY6MTIzNCw4ODE",
"navn": {
"fornavn": "Njål",
"etternavn": "Øye"
}
}
]
}
}
Trenger du oppslag fra andre gamle nøkkeltyper, finner du en fullstendig gjennomgang under Klienten må bruke FS GraphQL APIs ID for objektet i FS-API-guiden.
Tilgang: hvilken RAS-rolle trenger du?
FSWS-BAS ga deg hele datasettet med én tjenestetilgang. FS GraphQL API styrer i stedet tilgang på rad- og kolonnenivå med Oracle RAS, og de ulike delene av BAS treffer forskjellige roller. Du må derfor be om flere roller — én per datasett du faktisk bruker. Se Tilgangsstyring med RAS for bestillingsrutine.
Manglende rolle gir ingen feilmelding når du leser. Spørringen går gjennom, men du får færre rader, eller null i feltene rollen ikke dekker. Ser et uttrekk for lite ut etter migrering, er manglende rolle den vanligste årsaken — sjekk totalCount mot forventet volum. Ved skriving er oppførselen motsatt: mutasjonen feiler, eller endrer ingenting.
Tre ting er lette å gå i baklås på:
- Kull krever
STUDIEELEMENTER_LES2. Alle får automatiskSTUDIEELEMENTER_LES1, men den dekker ikke kull. UtenLES2returnererkulltomt, uten feilmelding. Se Grunnleggende tilgang. - Fagpersonroller gir ikke fødselsnummer.
FAGPERSONDATA_LES1ogLES2dekker ikke fødselsnummer for noen. Skal du slå opp en fagperson på fødselsnummer — altså erstatte BAS'nin-parameter — trenger duPERSONDATA_LES2. Uten den returnererfodselsnumre-filteret tomt, ogpersonProfil { fodselsnummer }girnull. Se Tilgang til persondata. - Skriverollene gir ikke lesetilgang.
PERSONDATA_SKRIV1lar deg oppdatere personprofilen, men ikke lese den. Mutasjonene i denne guiden returnerer det oppdaterte objektet i svaret, så du trenger som regel den tilhørende lese-rollen i tillegg.
For hendelsesspørringene (basEksport-erstatningen) er tilgangen delt opp per hendelseskategori, ikke samlet i én rolle:
Mangler du rollen for en kategori, forsvinner hendelsene i den kategorien fra svaret — uten varsel. Be om alle rollene du trenger samtidig når du bestiller tilgang.
Operasjoner som allerede er avviklet
Disse BAS-operasjonene er slått av og returnerer feil i dag. Har integrasjonen din fortsatt kall mot dem, er dette det mest akutte å rette.
To operasjoner har passert støttefristen (end of service 31.03.2025) uten å være slått av. De virker fortsatt, men Sikt gir ikke lenger brukerstøtte på dem: Hent steder ved institusjon og Oppdater en fagperson.
Resten av BAS — blant annet GET /hent/basdata, GET /hent/baseksport, POST /oppdater/bilde/form og POST /oppdater/brukernavn — har støttefrist 31. mars 2027.
Sjekk alltid avviklingsloggen for den gjeldende statusen. Datoene over var korrekte da guiden sist ble oppdatert.
POST /bas/oppdater/brukernavn — Oppdater brukernavn
Avvikles etter 31. mars 2027.
FSWS-BAS tillot oppdatering av en persons brukernavn ved å oppgi fødselsnummer. I FS GraphQL API erstattes dette av mutasjonen angiBrukerinformasjonForPersonProfiler.
Viktige forskjeller:
- FS GraphQL API bruker personprofil-ID i stedet for fødselsnummer. Slå opp ID-en med
personProfilerGittFodselsnumre— se IDer - Feltet heter
feideBrukeri stedet forbrukernavn - Du kan oppdatere
institusjonsEposti samme kall - Mutasjonen tar en liste, så du kan oppdatere flere personer i ett kall. BAS krevde ett kall per person
- Utelater du et felt, beholdes verdien som ligger inne. Sender du
nulleller tom streng"", tømmes feltet - Feil rapporteres i
errorsi svaret, ikke som HTTP-statuskode. Se Mutasjoner § Feilhåndtering
Eksempel på mutasjon:
mutation AngiBrukerinformasjon {
angiBrukerinformasjonForPersonProfiler(
input: [
{
id: "NzY6MTIzNCw4ODE"
feideBruker: "test"
institusjonsEpost: "bruker@institusjon.no"
}
]
) {
personProfiler {
id
feideBruker
institusjonsEpost
}
errors {
__typename
... on Error {
message
path
}
... on BrukernavnErIkkeUnikt {
message
}
... on InstitusjonsEpostErIkkeUnik {
message
}
}
}
}
errors er en union-type, ikke et vanlig objekt. Du må derfor selektere feltene gjennom inline fragments (... on ...) — errors { message } alene er ugyldig GraphQL. __typename forteller deg hvilken konkret feiltype du fikk. For denne mutasjonen er det én av UgyldigInput, BrukernavnErIkkeUnikt eller InstitusjonsEpostErIkkeUnik. Alle tre har feltene message og path, så ... on Error { message path } dekker dem samlet.
Eksempel på svar:
{
"data": {
"angiBrukerinformasjonForPersonProfiler": {
"personProfiler": [
{
"id": "NzY6MTIzNCw4ODE",
"feideBruker": "test@spusers.feide.no",
"institusjonsEpost": "bruker@institusjon.no"
}
],
"errors": null
}
}
}
Merk at feideBruker returneres med domene (test@spusers.feide.no) selv om du sendte inn brukernavnet uten. FS legger til lærestedets Feide-domene.
Blanke ut brukernavn og e-post
Sett feltene til null for å tømme dem. En tom streng "" gir samme resultat.
mutation BlankUtBrukerinformasjon {
angiBrukerinformasjonForPersonProfiler(
input: [
{
id: "NzY6MTIzNCw4ODE"
feideBruker: null
institusjonsEpost: null
}
]
) {
personProfiler {
id
feideBruker
institusjonsEpost
}
errors {
__typename
... on Error {
message
path
}
}
}
}
Eksempel på svar:
{
"data": {
"angiBrukerinformasjonForPersonProfiler": {
"personProfiler": [
{
"id": "NzY6MTIzNCw4ODE",
"feideBruker": null,
"institusjonsEpost": null
}
],
"errors": null
}
}
}
POST /bas/oppdater/bilde — Last opp/oppdater bilde
«Oppdater bilde for studenter» ble avviklet 26.01.2026. Varianten POST /oppdater/bilde/form har støttefrist 31. mars 2027.
FSWS-BAS tillot opplasting av bilder for personer. I FS GraphQL API erstattes dette av mutasjonen angiStudentbilder.
Viktige forskjeller:
- Krever student-ID (
StudentVedLarested) i stedet for fødselsnummer. Slå den opp medstudenter-spørringen ogfodselsnumre-filteret - Mutasjonen gjelder kun studenter. BAS kunne sette bilde på en person uavhengig av rolle
- Bildet må sendes som Base64-kodet streng i selve GraphQL-forespørselen — det finnes ikke et multipart-alternativ tilsvarende
/oppdater/bilde/form - Filtype angis eksplisitt som enum-verdi
JPGellerPNG - Finnes det allerede et bilde for studenten, erstattes det. Mutasjonen er altså «opprett eller oppdater», ikke bare opprett
Kontraktsnivå: beta. Krever headeren Feature-Flags: beta.
Eksempel på mutasjon:
mutation AngiStudentbilde {
angiStudentbilder(
input: [
{
studentVedLarestedId: "OTk6MTIzNCwxNDQw"
bilde: "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M9QDwADhgGAWjR9awAAAABJRU5ErkJggg=="
filtype: PNG
}
]
) {
studentbilder {
id
filtype
}
errors {
__typename
... on Error {
message
path
}
}
}
}
Eksempel på svar:
{
"data": {
"angiStudentbilder": {
"studentbilder": [
{
"id": "MTY1OjEyMzQsMTQ0MA",
"filtype": "PNG"
}
],
"errors": null
}
}
}
Merk at filtype i input er en enum (JPG eller PNG), mens filtype i svaret er en tekststreng med filendelsen. Vil du ha bildet tilbake, selekterer du også bilde — den returnerer hele den Base64-kodede fila, som fort blir mange hundre kilobyte. Ikke ta den med i spørringer der du bare trenger metadata.
Skal du slette et bilde, bruker du mutasjonen slettPersonbilder (beta), som tar ID-en til selve personbildet.
POST /bas/oppdater/email — Oppdater e-postadresse
Denne operasjonen er avviklet (25.03.2026) og returnerer feil i dag.
FSWS-BAS tillot oppdatering av en persons e-postadresse (PERSON.EMAILADRESSE) ved å oppgi fødselsnummer. I FS GraphQL API erstattes dette av mutasjonen endreEpostadresserForPersonProfiler.
Oppdatering av en persons e-postadresse er en del av tilgangsstyringsprosessen. Se Tilgangstyring for studenter og ansatte for en beskrivelse av prosessen og tilhørende GraphQL-mutasjoner.
Viktige forskjeller:
- FS GraphQL API bruker personprofil-ID i stedet for fødselsnummer
- BAS hadde ett e-postfelt. FS GraphQL API skiller mellom tre:
institusjonsEpost(tildelt av lærestedet — dette tilsvarer BAS' felt),privatEpostogarbeidsEpost. Du kan oppdatere alle tre i samme kall - Utelater du et felt, beholdes verdien som ligger inne. Sender du
nulleller tom streng, tømmes adressen
Eksempel på mutasjon:
mutation EndreEpostadresser {
endreEpostadresserForPersonProfiler(
input: [
{
id: "NzY6MTIzNCw4ODM"
privatEpost: "bruker@example.com"
arbeidsEpost: "bruker@arbeid.no"
}
]
) {
personProfiler {
id
privatEpost
arbeidsEpost
institusjonsEpost
}
errors {
__typename
... on Error {
message
path
}
... on InstitusjonsEpostErIkkeUnik {
message
}
... on PrivatEpostErIkkeUnik {
message
}
}
}
}
Eksempel på svar:
{
"data": {
"endreEpostadresserForPersonProfiler": {
"personProfiler": [
{
"id": "NzY6MTIzNCw4ODM",
"privatEpost": "bruker@example.com",
"arbeidsEpost": "bruker@arbeid.no",
"institusjonsEpost": null
}
],
"errors": null
}
}
}
POST /bas/oppdater/lanetakerid og /oppdater/semesteravgift
Begge operasjonene er avviklet (26.01.2026) og returnerer feil i dag.
Begge har erstatninger i FS GraphQL API, men foreløpig bare på experimental-nivå.
Kontraktsnivå: experimental. Krever headeren Feature-Flags: beta,experimental, og kan endres eller forsvinne uten varsel.
Viktige forskjeller:
- Begge tar student-ID (
StudentVedLarested) i stedet for fødselsnummer. Slå den opp medstudenter-spørringen ogfodselsnumre-filteret, eller medstudenterGittLanetakerIderhvis du allerede har lånetaker-ID-en - Semesteravgift registreres per termin. Du må oppgi termin-ID i tillegg til student-ID — BAS hadde ingen termin-parameter
- FS skiller mellom betalt og fritatt. Det er to ulike mutasjoner, ikke ett statusfelt
endreLanetakerIdForStudenterhar ingenerrors-blokk i svaret. Feil kommer som generelle GraphQL-feil på toppnivå, ikke i payloaden
Eksempel — ny lånetaker-ID:
mutation EndreLanetakerId {
endreLanetakerIdForStudenter(
input: [
{ id: "OTk6MTIzNCwxNDQw", lanetakerId: "987654321" }
]
) {
studenter {
id
lanetakerId
}
}
}
Eksempel — registrer betalt semesteravgift:
mutation RegistrerBetalt {
registrerSemesteravgiftBetaltForStudenter(
input: [
{
studentVedLarested: "OTk6MTIzNCwxNDQw"
termin: "MTA6MTIzNCwyMDI2LEjDmFNU"
betaltSemesteravgiftDato: "2026-09-01"
}
]
) {
semesterregistreringer {
erSemesterregistrert
harBetaltSemesteravgiftV2
}
errors {
__typename
... on Error {
message
path
}
... on SemesterSperretForOppdateringError {
message
}
... on UgyldigBetalingsOrganisasjonError {
message
}
}
}
}
Utelater du betaltSemesteravgiftDato, settes dagens dato. Skal studenten fritas i stedet for å betale, bruker du registrerFritakFraSemesteravgift med samme studentVedLarested og termin.
Trenger du disse i produksjon, ta kontakt med fs-support@sikt.no og be om at de løftes til beta.
POST /bas/oppdater/fagperson — Opprett eller oppdater fagperson
Støttefristen for «Oppdater en fagperson» (31.03.2025) er passert. Operasjonen virker fortsatt, men Sikt gir ikke lenger brukerstøtte på den.
FSWS-BAS tillot opprettelse og oppdatering av fagpersoner ved å sende inn én XML-representasjon. I FS GraphQL API er dette splittet: én mutasjon for opprettelse, og egne mutasjoner for oppdatering av enkeltområder.
Opprettelse og oppdatering av fagpersoner er en del av tilgangsstyringsprosessen. Se Tilgangstyring for studenter og ansatte for en beskrivelse av prosessen og tilhørende GraphQL-mutasjoner.
Viktige forskjeller:
- BAS brukte én XML-payload for både opprettelse og oppdatering. I FS GraphQL API må du velge riktig mutasjon for det du faktisk skal gjøre
- Fire felt er påkrevd ved opprettelse:
eierOrganisasjonskode,fodselsnummer,fornavnogetternavn - Er det allerede registrert en fagperson på personen, får du feilen
FagpersonFinnesForPersoni stedet for en oppdatering. Opprettelsen er ikke en «upsert» - Har fagpersonen ikke norsk fødselsnummer, D-nummer, SNR eller FS-fiktivt nummer, bruker du
opprettFagpersonerGittPassi stedet
Oppdateringsmutasjonene, med kontraktsnivå:
| Mutasjon | Hva den gjør | Kontraktsnivå |
|---|---|---|
aktiverFagpersoner | Aktiverer inaktive fagpersoner og vedlikeholder persondata | stable |
deaktiverFagpersoner | Deaktiverer, og fjerner institusjonsepost og Feide-bruker | stable |
angiBrukerinformasjonForPersonProfiler | Feide-brukernavn og institusjons-e-post | stable |
endreEpostadresserForPersonProfiler | Privat-, arbeids- og institusjons-e-post | stable |
endreArbeidsadresseForFagpersoner | Arbeidsadresse | experimental |
angiCampusForFagpersoner | Campus | experimental |
plasserFagpersonerPaaRom | Kontor-/romplassering | experimental |
De tre experimental-mutasjonene kan endres eller forsvinne uten varsel. Dekker de et behov du har i produksjon, ta kontakt med fs-support@sikt.no og be om at de løftes til beta.
Eksempel på opprettelse av fagperson:
mutation OpprettFagperson {
opprettFagpersonerGittFodselsnumre(
input: [
{
eierOrganisasjonskode: "1234"
fodselsnummer: "XXXXXXXXXXX"
fornavn: "Ola"
etternavn: "Nordmann"
arbeidsEpost: "ola.nordmann@institusjon.no"
feideBruker: "olanord"
}
]
) {
result {
personProfil {
id
navn {
fornavn
etternavn
}
}
fagperson {
id
erAktiv
ansattVed {
id
navnAlleSprak {
nb
}
}
}
}
errors {
__typename
... on Error {
message
path
}
... on FagpersonFinnesForPerson {
message
}
... on UgyldigFodselsnummer {
message
}
}
}
}
Mulige feiltyper er UgyldigInput, UgyldigFodselsnummer, UgyldigFodselsdatoFraFodselsnummer, UgyldigNorskTelefonnummer og FagpersonFinnesForPerson.
Eksempel på svar:
{
"data": {
"opprettFagpersonerGittFodselsnumre": {
"result": [
{
"personProfil": {
"id": "NzY6MTIzNCwzNzgw",
"navn": {
"fornavn": "Ola",
"etternavn": "Nordmann"
}
},
"fagperson": {
"id": "MzE6MTIzNCwzNzgw",
"erAktiv": true,
"ansattVed": null
}
}
],
"errors": null
}
}
}
Svaret gir deg begge ID-ene: personprofil-ID-en og fagperson-ID-en. Mutasjonene over tar den ene eller den andre — sjekk hvilken før du sender inn.
ansattVed er null fordi eksempelet ikke satte ansattVedOrganisasjonsenhetId ved opprettelse. Vil du knytte fagpersonen til en organisasjonsenhet, sender du ID-en med i input — slå den opp med organisasjonsenheterGittOrganisasjonsenhetskoder, se Hent steder.
GET /bas/hent/fagpersoner — Hent alle fagpersoner
Denne operasjonen er avviklet (25.03.2026) og returnerer feil i dag.
BAS hentet alle aktive fagpersoner med kontaktinfo, tilknytning (stedref) og roller. I FS GraphQL API erstattes dette av spørringen fagpersoner.
Viktige forskjeller:
- BAS returnerte XML, FS GraphQL API returnerer JSON
- Stedkoden (
stedref) erstattes av det nøstedeansattVed-objektet (enOrganisasjonsenhet) - Roller (studieprogramroller, emneroller, klasseroller med mer) hentes som nøstede felt på fagpersonen, i samme spørring
- Resultatet er paginert. BAS ga hele settet i ett svar
- Som i BAS returneres bare aktive fagpersoner som standard. Filteret har defaultverdiene
erAktiv: [true]ogerIPermisjon: [false]— setterAktiv: [true, false]hvis du også vil ha inaktive
Eksempel på spørring:
query AlleFagpersoner($after: String) {
fagpersoner(
filter: {
eierOrganisasjonskode: "1234"
}
first: 3
after: $after
) {
totalCount
pageInfo {
hasNextPage
endCursor
}
edges {
node {
id
personProfil {
fodselsnummer
navn {
fornavn
etternavn
}
}
erAktiv
ansattVed {
id
navnAlleSprak {
nb
}
}
}
}
}
}
Eksempel på svar:
{
"data": {
"fagpersoner": {
"totalCount": 412,
"pageInfo": {
"hasNextPage": true,
"endCursor": "Mw"
},
"edges": [
{
"node": {
"id": "MzE6MTIzNCw4ODM",
"personProfil": {
"fodselsnummer": "XXXXXXXXXXX",
"navn": {
"fornavn": "Njål",
"etternavn": "Øye"
}
},
"erAktiv": true,
"ansattVed": {
"id": "Nzk6MTIzNCwxODQsMywwLDA",
"navnAlleSprak": {
"nb": "Det medisinske fakultet, UiB"
}
}
}
}
]
}
}
}
Send endCursor fra svaret inn som $after i neste kall for å hente resten. Fortsett til hasNextPage er false.
Hente roller i samme spørring
BAS leverte fagpersonens roller i samme XML-dokument. Det kan du også gjøre her — legg rollefeltene til inne i node:
query FagpersonerMedRoller {
fagpersoner(filter: { eierOrganisasjonskode: "1234" }, first: 3) {
edges {
node {
id
studieprogramroller {
nodes {
fsRolle {
kode
}
studieprogram {
kode
}
gyldighetsperiode {
fraDato
tilDato
}
}
}
emneroller {
nodes {
fsRolle {
kode
}
}
}
klasseroller {
fsRolle {
kode
}
}
}
}
}
}
Merk at studieprogramroller og emneroller er paginerte og derfor må selekteres gjennom nodes (eller edges { node }), mens klasseroller returnerer en vanlig liste du selekterer direkte på. Inaktive roller filtreres bort som standard.
GET /bas/hent/fagperson — Hent en fagperson
Denne operasjonen er avviklet (25.03.2026) og returnerer feil i dag.
BAS hentet én fagperson basert på fødselsnummer (nin-parameteren). I FS GraphQL API bruker du samme fagpersoner-spørring som over, med fodselsnumre i filteret.
Viktige forskjeller:
nin-parameteren erstattes avfodselsnumre, som tar en liste. Du kan slå opp flere personer i ett kall- BAS returnerte XML, FS GraphQL API returnerer JSON
fagpersonerreturnerer som standard bare aktive fagpersoner som ikke er i permisjon. BAS' oppslag på fødselsnummer gjorde ikke denne filtreringen. Slår du opp en person som er inaktiv eller i permisjon, får du et tomt resultat med mindre du overstyrererAktivogerIPermisjon. Dette er den vanligste årsaken til at et oppslag som virket i BAS ser ut til å «mangle» data etter migrering- Resultatet er en paginert
Connection, ikke en flat liste — selekter gjennomnodeselleredges { node }
Eksempel på spørring:
query EnFagperson {
fagpersoner(
filter: {
eierOrganisasjonskode: "1234"
fodselsnumre: ["XXXXXXXXXXX"]
erAktiv: [true, false]
erIPermisjon: [true, false]
}
) {
nodes {
id
personProfil {
fodselsnummer
navn {
fornavn
etternavn
}
}
erAktiv
erIPermisjon
ansattVed {
id
navnAlleSprak {
nb
}
}
}
}
}
Eksempel på svar:
{
"data": {
"fagpersoner": {
"nodes": [
{
"id": "MzE6MTIzNCw4ODM",
"personProfil": {
"fodselsnummer": "XXXXXXXXXXX",
"navn": {
"fornavn": "Njål",
"etternavn": "Øye"
}
},
"erAktiv": true,
"erIPermisjon": false,
"ansattVed": {
"id": "Nzk6MTIzNCwxODQsMywwLDA",
"navnAlleSprak": {
"nb": "Det medisinske fakultet, UiB"
}
}
}
]
}
}
}
Bilde av fagpersonen
BAS leverte fagpersonens bilde i samme oppslag. Det tilsvarende feltet i FS GraphQL API er bilde på fagpersonen:
Kontraktsnivå: experimental. Krever headeren Feature-Flags: beta,experimental, og kan endres eller forsvinne uten varsel. Selve bilde-feltet er experimental, men typen det returnerer ligger på beta — derfor trengs begge flaggene.
query FagpersonMedBilde {
fagpersoner(
filter: {
eierOrganisasjonskode: "1234"
fodselsnumre: ["XXXXXXXXXXX"]
}
) {
nodes {
id
bilde {
bilde
filtype
}
}
}
}
Feltet bilde inne i bilde-objektet returnerer hele den Base64-kodede fila. Ta den bare med når du faktisk trenger bildedataene.
Trenger du fagpersonbilder i en produksjonsintegrasjon, ta kontakt med fs-support@sikt.no — feltet ligger foreløpig kun på experimental-nivå.
GET /bas/hent/kull — Hent alle kull
Denne operasjonen er avviklet (25.03.2026) og returnerer feil i dag.
BAS hentet alle aktive kull. I FS GraphQL API erstattes dette av spørringen kull.
Viktige forskjeller:
- BAS returnerte XML med kull-ID på formen
STUDIEPROGRAMKODE_ÅRSTALL_TERMIN. FS GraphQL API bruker en ugjennomsiktig ID, og eksponerer studieprogram og termin som egne nøstede felt du kan selektere - BAS returnerte bare kullnavnet. Her kan du hente alle feltene på kullet og på objektene det peker til
- Resultatet er paginert
- Som i BAS returneres bare aktive kull som standard (
erAktiv: [true]) - Feltet
terminer utfaset og fjernes. BrukterminV2i stedet — det er samme data, med riktig nullability
Eksempel på spørring:
query AlleAktiveKull {
kull(
filter: {
eierOrganisasjonskode: "1234"
erAktiv: [true]
}
first: 3
) {
edges {
node {
id
studieprogram {
kode
}
terminV2 {
arstall
betegnelse {
kode
navnAlleSprak {
nb
}
}
}
navnAlleSprak {
no
en
}
}
}
}
}
Eksempel på svar:
{
"data": {
"kull": {
"edges": [
{
"node": {
"id": "NTg6MTIzNCwxMCwxOTkzLEjDmFNU",
"studieprogram": {
"kode": "10"
},
"terminV2": {
"arstall": 1993,
"betegnelse": {
"kode": "HØST",
"navnAlleSprak": {
"nb": "Høst"
}
}
},
"navnAlleSprak": {
"no": "Studiekull 1993-HØST",
"en": null
}
}
}
]
}
}
}
Merk at kullnavnet bruker språkkodene no og en, mens terminnavnet bruker nb, nn og en. Hvilke språkkoder som finnes varierer per felt — bruk introspeksjon eller GraphiQL for å se hvilke som er tilgjengelige.
Fra BAS' kull-ID til GraphQL-ID
Har du lagret kull-ID-er på BAS-formen, kan du slå dem opp med kullGittLegacyIder:
Kontraktsnivå: experimental. Krever headeren Feature-Flags: beta,experimental.
query KullFraLegacyId {
kullGittLegacyIder(
eierOrganisasjonskode: "1234"
legacyIder: [
{ studieprogramkode: "10", arstall: 1993, terminkode: "HØST" }
]
) {
id
navnAlleSprak {
no
}
}
}
Trenger du dette oppslaget i produksjon, ta kontakt med fs-support@sikt.no og be om at det løftes til beta.
GET /bas/hent/sted — Hent steder ved en institusjon
Støttefristen (31.03.2025) er passert. Operasjonen virker fortsatt, men Sikt gir ikke lenger brukerstøtte på den.
BAS hentet organisasjonsenheter (steder) ved en institusjon. I FS GraphQL API erstattes dette av spørringen organisasjonsenheter.
Viktige forskjeller:
- BAS identifiserte et sted med den firedelte stedkoden (
institusjonsnr_faknr_instituttnr_gruppenr). FS GraphQL API bruker en ugjennomsiktig ID, men de fire delene finnes fortsatt som egne felt du kan selektere - Har du en firedelt stedkode og trenger tilsvarende ID, bruker du
organisasjonsenheterGittOrganisasjonsenhetskoder— se eksempelet under. Du trenger ikke å bla gjennom hele listen for å finne den - BAS returnerte XML, FS GraphQL API returnerer JSON
- Stedakronymet heter
forkortelse. Navneoversettelsene ligger undernavnAlleSprak - Resultatet er paginert
- Feltet
erAktivpå organisasjonsenhet ligger på beta-nivå, i motsetning tilerAktivpå fagperson, som er stable. Skal du selektere det, må du sendeFeature-Flags: beta. FiltereterAktiviorganisasjonsenheterer derimot stable, og har defaultverdien[true]— du får altså bare aktive enheter som standard, uten å måtte selektere feltet
Eksempel på spørring:
query AlleSteder {
organisasjonsenheter(
filter: {
eierOrganisasjonskode: "1234"
}
first: 3
) {
edges {
node {
id
navnAlleSprak {
nb
nn
en
}
forkortelse
organisasjon {
organisasjonskode
}
fakultet {
fakultetsnummer
}
instituttnummer
gruppenummer
}
}
}
}
Eksempel på svar:
{
"data": {
"organisasjonsenheter": {
"edges": [
{
"node": {
"id": "Nzk6MTIzNCwxODQsMywwLDA",
"navnAlleSprak": {
"nb": "Det medisinske fakultet",
"nn": null,
"en": "Faculty of Medicine"
},
"forkortelse": "MED",
"organisasjon": {
"organisasjonskode": "1234"
},
"fakultet": {
"fakultetsnummer": "184"
},
"instituttnummer": "3",
"gruppenummer": "0"
}
}
]
}
}
}
De fire feltene organisasjon.organisasjonskode, fakultet.fakultetsnummer, instituttnummer og gruppenummer utgjør til sammen den stedkoden BAS brukte.
Fra BAS' stedkode til GraphQL-ID
Har du lagret stedkoder på BAS-formen 1234_184_3_0, slår du opp tilsvarende organisasjonsenhet direkte:
query StedFraStedkode {
organisasjonsenheterGittOrganisasjonsenhetskoder(
eierOrganisasjonskode: "1234"
organisasjonsenhetskoder: [
{
organisasjonskode: "1234"
fakultetskode: "184"
instituttkode: "3"
gruppekode: "0"
}
]
) {
id
navnAlleSprak {
nb
}
forkortelse
}
}
Eksempel på svar:
{
"data": {
"organisasjonsenheterGittOrganisasjonsenhetskoder": [
{
"id": "Nzk6MTIzNCwxODQsMywwLDA",
"navnAlleSprak": {
"nb": "Det medisinske fakultet"
},
"forkortelse": "MED"
}
]
}
}
Alle fire kodedelene er påkrevd. Spørringen returnerer en flat liste, ikke en paginert Connection.
GET /bas/hent/baseksport — Inkrementell dataeksport
Avvikles etter 31. mars 2027.
BAS' basEksport ga deg endringene siden forrige uttrekk. I FS GraphQL API dekkes dette av hendelsesspørringene personProfilhendelser og studenthendelser.
Viktige forskjeller:
- Dette er polling, ikke push. FS GraphQL API har ingen
Subscription-type, og sender ikke hendelser til deg. Du spør med jevne mellomrom, akkurat som du kaltebasEksportmed jevne mellomrom - Du holder styr på hvor du er kommet ved hjelp av paginerings-markøren. Lagre
endCursorfra siste side du behandlet, og send den somafterneste gang. Da får du bare hendelser som har kommet til siden sist - Du må oppgi hvilke hendelsestyper du vil ha. Det finnes ikke et «gi meg alt»-alternativ
- Hendelsestypene er ulike for personprofil og student, og du må spørre hver av dem for seg
- Argumentnavnet er forskjellig i de to spørringene.
personProfilhendelserbrukerhendelsestyper(flertall),studenthendelserbrukerhendelsestype(entall). Begge tar en liste og begge er påkrevd. Dette er en kjent inkonsistens — bruk nøyaktig det navnet som hører til spørringen - Hendelsestypene er union-/interface-baserte:
hendelsestypeogtidspunktfinnes på alle, mens feltene som forteller hva som faktisk endret seg ligger på den konkrete typen. Selekter dem gjennom inline fragments
Hendelser krever egen tilgang, og rollen er delt opp per hendelseskategori. Se Tilgang: hvilken RAS-rolle trenger du? for hvilke roller hendelsestypene under krever, og FS GraphQL API: Hendelser for full oversikt over hendelsestypene.
Eksempel — endringer i brukerinformasjon:
query PersonProfilEndringer($after: String) {
personProfilhendelser(
filter: {
eierOrganisasjonskode: "1234"
hendelsestyper: [
PERSONPROFIL_ENDRET_INSTITUSJONSEPOST
PERSONPROFIL_ENDRET_PRIVAT_EPOST
PERSONPROFIL_ENDRET_NAVN
]
}
first: 100
after: $after
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
__typename
hendelsestype
tidspunkt
... on PersonProfilEndretInstitusjonsepost {
personProfil {
id
institusjonsEpost
}
}
... on PersonProfilEndretNavn {
personProfil {
id
navn {
fornavn
etternavn
}
}
}
}
}
}
Eksempel på svar:
{
"data": {
"personProfilhendelser": {
"pageInfo": {
"hasNextPage": false,
"endCursor": "Mg"
},
"nodes": [
{
"__typename": "PersonProfilEndretInstitusjonsepost",
"hendelsestype": "PERSONPROFIL_ENDRET_INSTITUSJONSEPOST",
"tidspunkt": "2026-09-16T08:14:22Z",
"personProfil": {
"id": "NzY6MTIzNCw4ODE",
"institusjonsEpost": "ny.adresse@institusjon.no"
}
}
]
}
}
}
På stabilt nivå finnes disse personprofil-hendelsestypene: PERSONPROFIL_ENDRET_PRIVAT_EPOST, PERSONPROFIL_ENDRET_INSTITUSJONSEPOST, PERSONPROFIL_ENDRET_ARBEIDSEPOST, PERSONPROFIL_ENDRET_NAVN og PERSONPROFIL_ENDRET_FODSELSNUMMER.
Eksempel — studenthendelser (merk hendelsestype i entall):
query StudentEndringer($after: String) {
studenthendelser(
filter: {
eierOrganisasjonskode: "1234"
hendelsestype: [SLUTTET_PA_STUDIEPROGRAM, STUDIERETT_FORLENGET]
}
first: 100
after: $after
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
__typename
hendelsestype
tidspunkt
student {
id
personProfil {
fodselsnummer
}
}
}
}
}
På stabilt nivå finnes bare SLUTTET_PA_STUDIEPROGRAM og STUDIERETT_FORLENGET. Trenger du hendelser som ENDRET_FEIDE_BRUKER, SEMESTERREGISTRERT, ENDRET_LANETAKER_ID, STUDENTKORT_UTSTEDT eller DODSFALL — som ligger tettere opp mot det basEksport dekket — ligger de på beta-nivå og krever headeren Feature-Flags: beta.
GET /bas/hent/basdata — Full dataeksport
Avvikles etter 31. mars 2027.
BAS' basData ga ett fast, fullt datasett. I FS GraphQL API setter du selv sammen en spørring som henter nøyaktig de feltene du trenger.
Viktige forskjeller:
- Datasettet er ikke lenger fast. Du velger felt, og får bare det du ber om
- Resultatet er paginert — du må bla gjennom sidene for å få hele bestanden
- Studenter og fagpersoner er to adskilte spørringer. BAS leverte begge i samme uttrekk
- Trenger du bare endringene siden sist, er hendelsesspørringene over et vesentlig billigere alternativ enn å hente alt på nytt
Eksport av studenter
Eksempelet under bruker studenter med fodselsnumre-filteret for å vise ett bestemt tilfelle. Utelat fodselsnumre for å hente hele bestanden — da må du paginere.
Kontraktsnivå: blandet. vurderingsmeldingerV2 er beta, studentkort er experimental. Send Feature-Flags: beta,experimental for å få begge. Resten er stable — trenger du bare de stabile feltene, kan du droppe de to blokkene og kjøre uten header.
query StudentEksport($after: String) {
studenter(
filter: {
eierOrganisasjonskode: "1234"
fodselsnumre: ["XXXXXXXXXXX"]
}
first: 100
after: $after
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
studentnummer
lanetakerId
personProfil {
fodselsnummer
feideBruker
institusjonsEpost
navn {
fornavn
etternavn
}
}
semesterregistreringer {
nodes {
termin {
arstall
betegnelse {
kode
}
}
erSemesterregistrert
harBetaltSemesteravgiftV2
}
}
vurderingsmeldingerV2 {
nodes {
id
emne {
kode
versjonskode
navnAlleSprak {
nb
}
}
}
}
studentkort {
studentkortnummer
gyldighetsperiode {
fraDato
tilDato
}
}
}
}
}
Tre ting å merke seg:
harBetaltSemesteravgiftV2, ikkeharBetaltSemesteravgift. Feltet utenV2er utfaset og fjernes.V2er det som gjelder, og dekker både betalt avgift og innvilget fritakvurderingsmeldingerV2, ikkevurderingsmeldinger. Feltet utenV2hadde fjerningsdato 15.04.2026 og bør ikke brukes i ny kode.V2er paginert, så du må selektere gjennomnodeselleredges { node }studentkorter experimental og returnerer en liste — en student kan ha flere kort over tid. Trenger du studentkort i produksjon, ta kontakt med fs-support@sikt.no
Eksempel på svar (forkortet):
{
"data": {
"studenter": {
"pageInfo": {
"hasNextPage": false,
"endCursor": "MQ"
},
"nodes": [
{
"id": "OTk6MTIzNCwxNDQw",
"studentnummer": "123456",
"lanetakerId": "987654321",
"personProfil": {
"fodselsnummer": "XXXXXXXXXXX",
"feideBruker": "olanord@spusers.feide.no",
"institusjonsEpost": "ola.nordmann@institusjon.no",
"navn": {
"fornavn": "Ola",
"etternavn": "Nordmann"
}
},
"semesterregistreringer": {
"nodes": [
{
"termin": {
"arstall": 2026,
"betegnelse": { "kode": "HØST" }
},
"erSemesterregistrert": true,
"harBetaltSemesteravgiftV2": true
}
]
},
"vurderingsmeldingerV2": {
"nodes": [
{
"id": "MTE0OjEyMzQsNTU4MQ",
"emne": {
"kode": "INF100",
"versjonskode": "1",
"navnAlleSprak": {
"nb": "Innføring i programmering"
}
}
}
]
},
"studentkort": []
}
]
}
}
}
Eksport av fagpersoner
query FagpersonEksport($after: String) {
fagpersoner(
filter: {
eierOrganisasjonskode: "1234"
}
first: 100
after: $after
) {
pageInfo {
hasNextPage
endCursor
}
nodes {
id
erAktiv
erIPermisjon
personProfil {
fodselsnummer
feideBruker
institusjonsEpost
navn {
fornavn
etternavn
}
}
ansattVed {
id
navnAlleSprak {
nb
}
}
stillingstittelAlleSprak {
no
en
}
studieprogramroller {
nodes {
fsRolle {
kode
}
studieprogram {
kode
}
gyldighetsperiode {
fraDato
tilDato
}
}
}
}
}
}
studieprogramroller er paginert, så feltene må selekteres gjennom nodes (eller edges { node }). Dette gjelder også emneroller. klasseroller er en vanlig liste.
Disse spørringene kan tilpasses videre for å hente akkurat de feltene du trenger. Bruk GraphiQL og introspeksjon for å utforske hvilke felt som finnes.
Kontakt oss for hjelp ved behov
Ta kontakt med fs-support@sikt.no dersom du trenger hjelp til å komme i gang, eller underveis i migreringen. Det gjelder også hvis du finner at et felt du er avhengig av bare finnes på experimental-nivå — vi trenger å vite om reelle behov for å kunne prioritere å løfte dem.