Denne side beskriver adgangen til og den tekniske distribution af GraphQL, som er gældende for alle registre på Datafordeleren, der udstiller data med GraphQL.

Siden beskriver hvordan anvendere på Datafordeleren kan benytte GraphQL-tjenesterne til at hente tabulære data fra registrene.





Begreber


På siderne om GraphQL bruges nedenstående begreber. Bemærk at begreberne også bliver yderligere forklaret med eksempler på siderne.

Begreb

Beskrivelse

Nuværende Datafordeler

REST-tjenester:

REST-tjenester er en metode til at få data fra Datafordeleren. Du kan som anvender hente data ved at bruge en URL. REST-tjenester er beskrevet på REST på Datafordeleren.

Moderniserede Datafordeler

GraphQL:

GraphQL beskrives i denne vejledning.

Entitet:

En entitet er en fysisk repræsentation af et registerobjekt som findes i Grunddatamodellen. De total- og deltadownload, der kan hentes fra Datafordeleren, samt de entitetsbaserede GraphQL-tjenester indeholder hver især data bestående af en enkelt entitet.

GraphQL-skemaer:

GraphQL-skemaer er .graphql-filer der genereres på baggrund af registrenes datamodeller og er yderligere beriget med metadata fra hvert register. Skemaerne beskriver hvordan data er struktureret og hvordan data kan hentes.

Paging:

Paging er når resultater inddeles i sider således at resultater returneres én side ad gangen.







Hvad er GraphQL?


GraphQL er et moderne API-sprog, der gør det muligt at hente data på en effektiv og fleksibel måde. GraphQL giver mulighed for at hente præcis de oplysninger, du som anvender skal bruge. GraphQL-tjenesterne er derfor velegnede når du ønsker at hente mindre datamængder og ikke nødvendigvis ønsker at postprocessere data efterfølgende.

Du kan bruge GraphQL-tjenesterne ved at sende en forespørgsel, der beskriver de data du ønsker, til Datafordeleren, hvorefter serveren kun svarer med de specifikke data, der blev anmodet om. Dette kan du blandt andet gøre gennem en desktop applikation eller gennem browseren ved brug af en browser-extension.

Med GraphQL kan du definere hvilke datafelter du ønsker returneret. Dette betyder, at du kun modtager de oplysninger, du har brug for. Det kan dermed forbedre svartiden for tjenesterne og reducere mængden af data, som overføres.

Yderligere information om GraphQL kan findes på graphql.org.

Måden du bruger GraphQL-tjenesterne på, er ved at sende en såkaldt query til et af Datafordelerens GraphQL-endepunkter. En query er anvendernes måde at definere hvilke data du ønsker at hente.

Et eksempel på en query mod tjenesten https://graphql.datafordeler.dk/BBR/v1 kan ses nedenfor.





GraphQL-queries fungerer således:

  • Entitet 
    • En query skal specificere hvilken entitet den omhandler.
    • Eksemplet ovenfor viser en query for entiteten BBR_Bygning fra BBR.
  • Tjeneste 
    • En query skal sendes til en GraphQL-tjeneste, der indeholder den pågældende entitet, som et GET- eller POST-request.
  • Standardfiltre 
    • En query kan indeholde standardfiltre der filtrerer data.
    • Eksemplet ovenfor indeholder to standardfiltre: lighedsoperator (eq: "0550") på kommunekode og (eq: "6") på status.
  • Geometriske filtre 
    • En query kan indeholde geometriske filtre, der filtrerer data på baggrund af geometri-felter.
  • Bitemporale filtre 
    • En query kan indeholde bitemporale filtre, der filtrerer data på baggrund af bitemporale felter.
    • Eksemplet ovenfor indeholder bitemporalt point-in-time-filter (virkningstid: "2024-11-12T14:41:33Z") på virkningstidspunktet og (registreringstid: "2025-03-23T14:41:33Z ") på registreringstidspunktet.
  • Minimumsfiltrering 
    • På bitemporale entiteter skal en query indeholde mindst et bitemporalt point-in-time-filter eller et standardfilter på feltet id_lokalid.
    • Eksemplet ovenfor indeholder to bitemporale point-in-time-filtre, og opfylder derfor minimumsfiltrering.
  • Paging 
    • En query skal definere hvilke felter fra entiteten der forespørges og hvordan resultaterne paging.
    • Eksemplet ovenfor returnerer de første 10 resultater (first: 10) for felterne (angivet i ”nodes”) id_lokalid, kommunekode, virkningsaktoer, forretningsproces samt paging-informationer (angivet i ”pageInfo”) for resultatsættet.
  • Schema 
    • Hvorvidt en query er gyldig vurderes iht. GraphQL-skemaet, der definerer hvordan data er struktureret, hvilke typer af data der kan hentes, mulige filtreringsoperationer mm.






Om entitetsbaserede GraphQL-tjenester


GraphQL-tjenester tilbydes som entitetsbaserede GraphQL-tjenester. Entiteterne baserer sig på datamodeller fra Grunddatamodellen. En entitet kan f.eks. være en "Adresse" fra DAR, en "Bygning" fra BBR eller et "Jordstykke" fra MAT.

Det at GraphQL-tjenesterne er entitetsbaserede betyder at et kald til en af tjenesterne returnerer data for en enkelt type af entitet. De entitetsbaserede GraphQL-tjenester leverer udelukkende tabulære data og ikke rasterdata (billeddata). Tabulære data forstås som strukturerede data der kan opbevares i tabeller, som f.eks. adresser, men ikke billeddata som f.eks. skærmkort.




Nedenstående figur giver et overblik over konceptet for entitetsbaserede GraphQL-tjenester. Figuren illustrerer 3 fiktive registre:

  • Register A, som har 5 entiteter. Registerets entiteter refererer til hinanden indbyrdes indenfor registeret og har også en enkelt reference til en entitet i register C udenfor registeret.
  • Register B, som har 6 entiteter. Registerets entiteter refererer til hinanden indbyrdes indenfor registeret og har også en enkelt reference til en entitet i register A udenfor registeret.
  • Register C, som har 6 entiteter. Registerets entiteter refererer til hinanden indbyrdes indenfor registeret.





Figuren illustrerer at entitetsbaserede GraphQL-tjenester ikke udstiller relationer mellem entiteter, samt at tjenesterne ikke kan sammenstille entiteter. Den understøttede funktionalitet uddybes i de følgende afsnit.






GraphQL-endepunkter


GraphQL-tjenesterne udstilles gennem URL'er, der følger nedenstående form:

https://graphql.datafordeler.dk/<register>/<version>

<register> er forkortelsen for det register du som anvender forsøger at hente og <version> er versionen for det pågældende register. Versionering er yderligere beskrevet i afsnittet Versionering

Alle registre, hvis entiteter udstilles via GraphQL-tjenesterne, er vist nedenfor.




Register

Forkortelse

Bygnings- og Boligregistret

BBR

Danmarks Administrative Geografiske Inddeling

DAGI

Danmarks Adresseregister

DAR

Danmarks Fikspunktregister

FIKSPUNKT

DHM Højdekurver

DHMHoejdekurver

DHM Oprindelse

DHMOprindelse

Danske Stednavne

DS

Det Centrale Virksomhedsregister

CVR

Ejendomsbeliggenhedsregistret

EBR

Ejendomsvurdering

VUR

Ejerfortegnelsen

EJF

GeoDanmark Vektor

GEODKV

Historiske kort og data

HISTKORT

Matriklen2

MAT

Skatteforvaltningens Virksomhedsregister

SVR







Adgangsbegrænsede registre


Nogle registre indeholder data, f.eks. personoplysninger, som kræver godkendelse for at kunne tilgås. Disse data kaldes på Datafordeleren for adgangsbegrænsede data.

Adgang til adgangsbegrænsede data tildeles af registrene ved at en anvender opretter et IT-system og laver en ansøgning gennem selvbetjeningen til det specifikke register på vegne af det nyoprettede IT-system, hvorefter det pågældende register først skal godkende ansøgningen før data kan tilgås. Læs mere om Brugeradgang  datafordeler.dk og hvordan et IT-system oprettes på IT-systemer.

Tabellen nedenfor viser hvilke registre der indeholder adgangsbegrænsede data:


Register

Entiteter

CVR

CVRPerson

EJF

Alle entiteter

SVR

Alle entiteter


Bemærk

Der er kun adgang til de fortrolige entiteter fra EJF for offentlige myndigheder.







Specialudviklet GraphQL-tjeneste for CVR


Entiteten CVRPerson fra CVR har et enkelt felt som indeholder adgangsbegrænsede data, mens resten af felterne ikke er adgangsbegrænsede. Datafordeleren udstiller derfor den specialudviklede entitet CVRPersonBegraenset gennem en GraphQL-tjeneste, der giver anvendere mulighed for at hente en ikke-adgangsbegrænset udgave af entiteten CVRPerson. Entiteten CVRPersonBegraenset er identisk med CVRPerson bortset fra at feltet CPRPerson er fjernet.

Filtreringsmulighederne på CVRPersonBegraenset-entiteten er de samme som tillades på CVRPerson-entiteten, bortset fra at det ikke er muligt at filtrere på CPRPerson-feltet. GraphQL-skemaet ligner det for CVRPerson-entiteten, dog uden CVRPerson-feltet.

Tjenesten er tilgængelig på følgende URL:

https://graphql.datafordeler.dk/CVR/custom/<version>






Standardfiltrering


GraphQL-tjenesterne understøtter almindelige sammenligningsoperatorer og filtreringsmuligheder (f.eks. <, >, =, in). Nedenstående tabel viser eksempler på datatyper og understøttede operatorer. Det skal bemærkes, at det fremgår i GraphQL-skemaerne for de enkelte registre, hvilke filtreringsmuligheder der er for hver entitet og dennes felter. Tabellen kan ikke anvendes som reference når der skal sammensættes queries til det enkelte register, da det afhænger af den specifikke entitet og dennes felter præcis hvilke operatorer der er understøttet. Læs mere om GraphQL-skemaer.

Det er muligt at bruge flere filtre i den samme query, selvom der er nogle begrænsninger for, hvordan filtrering er tilladt.


Datatyper

Understøttede operatorer

Comparable (Float, Int, Long, Short)

  • In
  • Equal to (eq)
  • Less than (lt)
  • Less than or equal to (lte)
  • Not less than (nlt)
  • Not less than or equal to (nlte)
  • Greater than (gt)
  • Greater than or equal to (gte)
  • Not greater than (ngt)
  • Not greater than or equal to (ngte)

Comparable (Date, DateTime, TimeSpan)

  • Equal to (eq)
  • Less than (lt)
  • Less than or equal to (lte)
  • Not less than (nlt)
  • Not less than or equal to (nlte)
  • Greater than (gt)
  • Greater than or equal to (gte)
  • Not greater than (ngt)
  • Not greater than or equal to (ngte)

Text (String)

  • In
  • Equal to (eq)
  • Starts with (startsWith)

Boolean

  • Equal to (eq)
  • Not equal to (neq)

Bemærk

Det fremgår i GraphQL-skemaet for det enkelte register, hvilke filtreringsmuligheder der kan anvendes for de enkelte entiteter og deres felter. 

Tabellen kan ikke anvendes som reference når der skal sammensættes queries til det enkelte register, da det afhænger af den specifikke entitet og dennes felter præcis hvilke operatorer der er understøttet.






Geometrisk filtrering


GraphQL-tjenesterne understøtter også geospatiale data og du kan derfor benytte filtre i form af WKT-strenge (Well Known Text) som gives som input til de geometriske filtre. Disse WKT'er repræsenterer geospatiale data, enten i form af en koordinattype, en geometri-type eller lignende datatyper.

De mest almindelige typer af geometriske former er punkter, linjer og polygoner. Et punkt repræsenteres af et koordinatsæt med to eller tre værdier, afhængigt af om det er et punkt i to eller tre dimensioner. En linje repræsenteres af koordinatparrene eller koordinattripletterne for de punkter, der udgør linjen, og en polygon repræsenteres af koordinatpar eller koordinattripletter, der udgør hjørnerne af polygonen. Et eksempel på WKT-formatet for hver af de tre geometrityper i 2D, er vist i nedenstående figur.




Point

 POINT (3 5)

Line

LINESTRING (6 4, 8 2, 7 1)

Polygon

 POLYGON (1 1, 3 3, 4 2, 4 0, 1 1)




Datafordeleren understøtter en række forskellige operatorer. Alle operatorerne fremgår sammen med et link til deres PostGIS-dokumentation i tabellen nedenfor, og hver af funktionerne tager to geometriske former og returnerer en Boolean værdi. Kombinationer af forskellige filtre understøttes også ved hjælp af AND/OR-operatorer.




Datatyper

Understøttede operatorer

PostGis Link

Geometri

contains(koordinatsystem, geometri)

https://postgis.net/docs/ST_Contains.html

covers(koordinatsystem, geometri)

https://postgis.net/docs/ST_Covers.html

coveredBy(koordinatsystem, geometri)

https://postgis.net/docs/ST_CoveredBy.html

crosses(koordinatsystem, geometri)

https://postgis.net/docs/ST_Crosses.html

intersects(koordinatsystem, geometri)

https://postgis.net/docs/ST_Intersects.html

within(koordinatsystem, geometri)

https://postgis.net/docs/ST_Within.html

overlaps(koordinatsystem, geometri)

https://postgis.net/docs/ST_Overlaps.html​

touches(koordinatsystem, geometri)

https://postgis.net/docs/ST_Touches.html




Et eksempel på hvordan operatoren contains bruges kan ses i nedenstående figur.





De geometriske filtre er implementeret således, at hvis man læser informationen i PostGIS-dokumentation link i tabellen ovenfor, er geometri A altid værdien af registerdatafeltet, og geometri B altid inputgeometrien. Det vil sige, at rækkefølgen er operator(<registerdatafelt>, <input>). Hvis du ønsker den modsatte rækkefølge, bør du i stedet bruge en anden geometrisk operator, der repræsenterer den omvendte operator. En oversigt over disse kan ses i nedenstående tabel.

Geometrisk operator

Omvendte operator

contains

within

covers

coveredBy

coveredBy

covers

crosses

Ingen. crosses er symmetrisk

intersects

Ingen. intersects er symmetrisk

within

contains

overlaps

Ingen. overlaps er symmetrisk

touches

Ingen. touches er symmetrisk




Syntaksen for at bruge geometriske filtre, og hvilke felter der kan filtreres geometrisk, er specificeret af GraphQL-skemaet for den pågældende tjeneste, som du ønsker at bruge.

Da geospatiale data kan have forskellige formater afhængigt af, hvilket register det drejer sig om, udfører Datafordeleren udelukkende validering på om det angivne koordinatsystem (CRS) er det samme koordinatsystem som registrets data og at den angivne WKT er valid og repræsenterer en topologisk valid geometri som specificeret i OGC SFS-specifikationen.






Bitemporal filtrering 


På entiteter med bitemporale felter (forklares nærmere på Bitemporalitet datafordeler.dk) er følgende to typer queries ofte anvendt:

  • Interval-queries, hvor du ønsker data, der er bitemporalt gyldige i en bestemt tidsperiode.
  • Point-in-time-queries, hvor du ønsker bitemporalt gyldige data pr. deres angivne tidspunkt.

Ved interval-queries har du mulighed for at specificere standardfiltre, på de bitemporale felter. Ved point-in-time-queries understøttes valgfrie argumenter for registreringstid og virkningstid, som kan angives, når du sender queries. Når disse argumenter ikke gives, returneres fuldt bitemporale data. 

GraphQL-tjenesterne understøtter muligheden for at kombinere point-in-time-filtrering med enhver anden filtrering, der er tilladt, så du kan hente data, der overholder det angivne tidspunkt samt eventuelle intervalfiltre, geo-filtre eller lignende, du har angivet. Det vil sige, når point-in-time-filteret kombineres med andre filtre, vil forespørgslen ende med at være "point-in-time-filter OG (andre filtre)". Det er ikke muligt at sige point-in-time-filtreret 'ELLER' noget andet filter.

Bemærk

For at få data som er gyldigt på et givent tidspunkt, skal du sætte både virkningstid og registreringstid til forespørgselstidspunktet for at få data, der er gyldige på det pågældende tidspunkt.







Bitemporal filtrering for CVR


Alle registre der understøtter bitemporal filtrering, understøtter filtrering på både virkningstidspunkt og registreringstidspunkt bortset fra CVR. CVR er det eneste register, hvor du ikke kan specificere et registreringspunkt i din query. For CVR sættes registreringstidspunktet derimod altid til tidspunktet for forespørgslen, dvs. “registreringstid = NOW()”. Det er muligt at filtrere på virkningstidspunktet på sædvanlig vis.







Minimumsfiltrering


På entiteter med bitemporale felter kræves minimum ét af følgende filtre:

Filtreringstype

Filter

Bitemporal filtrering

Point-in-time filter på registreringstid

Bitemporal filtrering

Point-in-time filter på virkningstid

Standardfiltrering

Operator på feltet id_lokalid






Paging


GraphQL-tjenesterne kræver paging af resultater. At resultaterne pagineres vil sige at resultaterne inddeles i ”sider” og returneres én ad gangen. Du vil således få én side returneret ad gangen og kan efterfølgende lave et nyt kald for at få næste side for på den måde at gennemgå hele datasættet.

Paging er cursor-baseret, hvilket vil sige at der returneres en reference, en såkaldt cursor, til første og sidste resultat (for edges ved hvert enkelt resultat) i det returnerede datasæt ved hvert kald. Denne cursor kan derefter bruges til at hente flere sider ved at anmode om mere data fra cursorens værdi. I praksis kan du bruge cursor-værdien i en efterfølgende query, til at hente den næste side af data, startende fra den position, der er angivet ved den pågældende cursor. Paging er implementeret således at flere identiske anmodninger ved hjælp af den samme cursor vil returnere de samme data, forudsat at registrene ikke opdaterer de underliggende data i mellemtiden.

Paging er udelukkende implementeret som fremadgående paging. Det vil sige, at du kan hente den næste side af resultater fra en given cursor. Bagudgående paging understøttes ikke.







Paging i queries: PageInfo, nodes og edges


Paging består af tre datastrukturer: PageInfo samt nodes eller edges.

PageInfo indeholder metadata om den nuværende paging og består af følgende felter:

  • hasNextPage: Dette felt angiver, om der er endnu en side med resultater.
  • hasPreviousPage: Dette felt angiver, om der eksisterer en forrige side med resultater. Da vi ikke understøtter bagudgående paging, er dette altid sat til false.
  • startCursor: Dette felt er en cursor, der peger på det første datapunkt i resultatdatasættet.
  • endCursor: Dette er en cursor, der peger på det sidste datapunkt i resultatsættet. Denne cursor kan bruges af anvenderen til at hente den næste side af data.

Mens metadata kan hentes via PageInfo, kan data hentes enten som en liste af nodes eller en liste af edges. Nodes og edges adskiller sig på følgende måde:

  • I resultatsættet er nodes en liste af datapunkter.
  • I resultatsættet er edges en liste af datapunkter med et ekstra metadatafelt cursor, der matcher hvert datapunkt.

Det anbefales, at du benytter nodes til simpel paging, da PageInfo-metadataene er tilstrækkelige. Hvis du har brug for at paging fra en hvilken som helst position på den aktuelle side og ikke fra slutningen af den aktuelle side, skal edges benyttes.

Det er tilladt for anvendere at specificere i GraphQL-queries, at de ønsker både nodes og edges returneret. Dette frarådes, da resultatsættet vil indeholde de samme data to gange.







Inputargumenter for paging


Paging har to inputargumenter, der kan specificeres i en query:

  • first: Dette argument angiver hvor mange resultater der ønskes returneret. Dette er sidestørrelsen og skal være et ikke-negativt tal. Hvis dette argument udelades fra en query, returneres standardantallet (100) af resultater. Den maksimalt tilladte sidestørrelse er 1000, og hvis værdien af first er større end den maksimalt tilladte sidestørrelse returneres en fejlmeddelelse.
  • after: Dette argument angiver cursoren til det første datapunkt i det resulterende datasæt. Hvis dette argument udelades fra query’en, returneres den første side.

Hvis du angiver ugyldige værdier for nogen af disse argumenter, vil tjenesterne returnere en fejlmeddelelse, der informerer om, at der er angivet ugyldige paging-argumenter.







Eksempel på paging-query


Følgende query kan bruges til at hente de første 5 datapunkter (første side) af BBR_Bygning-entiteten:





Tjenesten returnerer følgende resultat:





Fra hasNextPage i resultatet ovenfor kan man se at der er flere sider, da den er sat til true. For at hente den næste side kan du derfor bruge endCursor som after-værdi i den efterfølgende query:





Ved iterativt at gentage dette mønster kan alt den ønskede data hentes.






GraphQL-skemaer


For alle de registre der er udstillet gennem Datafordelerens GraphQL-tjenester, kan du hente GraphQL-skemaer, der beskriver hvordan data er struktureret. Skemaerne specificerer de typer data, der kan hentes, relationerne mellem disse typer og de filtreringsoperationer, der kan understøttes for de pågældende felter. Du kan benytte skemaerne til at se hvilke queries du kan sende, og hvilke data du kan hente.

Skemaerne genereres på baggrund af registrenes datamodeller og er beriget med metadata for hvert register. Denne metadataudtrækningsproces involverer at tage relevant information fra datamodellerne og inkorporere den i skemaerne. Denne ekstra metadata giver anvendere mere omfattende indsigt i de tilgængelige data. Skemaerne findes separat for hvert register og kan hentes ved at tilgå nedenstående url:

https://graphql.datafordeler.dk/<register>/<version>/schema

<register> er forkortelsen for det register anvenderen forsøger at hente og <version> er versionen for det pågældende register. Skemaet for version 1 af Skatteforvaltningens Virksomhedsregister (SVR) hentes for eksempel på følgende url:

https://graphql.datafordeler.dk/SVR/v1/schema






Versionering


I GraphQL-tjenesterne versioneres hvert register separat, og alle entiteter, der tilhører det samme register, versioneres under det samme versionsnummer som registret. Det vil sige, at DAR og BBR kan eksistere separat som DAR/v2 og BBR/v5. Men hvis BBR har en change til Bygning-entiteten i deres datamodel, vil alle entiteter i BBR blive opgraderet til BBR/v6, og BBR/v5 vil derefter efter en overgangsperiode blive udfaset.






Cost-beregning


Som en sikkerhedsforanstaltning og af performance-hensyn tilskrives hver query en cost. En cost er en beregnet talværdi der indfanger hvor kompleks og omkostningstung en given query er for Datafordeleren at processere. Cost udregnes inden en query processeres. 

Udregningen af cost er blandt andet baseret på følgende specifikationer:

  • Sidestørrelse: Størrelse på paging-siderne der returneres. Jo større sider, jo mere data returneres, hvilket giver en højere cost.
  • Filtre: Antallet og type af filtre der benyttes i en query påvirker cost. Jo flere filtre, jo højere cost. Derudover er geometri-filtre mere omkostningstunge og resulterer derfor i en højere cost. 
  • Entiteter: Almindelige og store entiteter har forskellige omkostninger associeret med dem. Store entiteter er mere omkostningstunge end mindre entiteter.
  • Felter: Forskellige typer felter har forskellige omkostninger. Geometrier og sammensatte felter er dyrere end simple felter. (Et sammensat felt er et felt der indeholder andre felter.)

Bemærk

Der håndhæves aktuelt ikke en grænse på cost før en query processeres af Datafordeleren. 

Det er dog en mulighed der kan finde anvendelse hvis der skulle opstå et behov. 

Såfremt dette behov skulle opstå, vil det blive kommunikeret inden der etableres en max cost på GraphQL tjenesterne.






Sådan anvender du entitetsbaserede GraphQL-tjenester


GraphQL-tjenesterne på Datafordeleren tilgås via et GraphQL-API. Dette afsnit beskriver, hvordan det vil være muligt at danne et overblik over hvilke entiteter du kan tilgå, samt hvordan data hentes.

GraphQL-tjenesterne kan tilgås på registerbasis og kræver at du benytter en af de tre autentifikationsmetoder







Ovenstående figur viser hvordan GraphQL-API'et overordnet set anvendes. Her hentes GraphQL-skemaet først for det pågældende register ved at tilgå https://graphql.datafordeler.dk/<register>/<version>/schema, hvorefter det ønskede data hentes, ved at sende en query til https://graphql.datafordeler.dk/<register>/<version>.







Hent Schema


Hent Schema

URL

https://graphql.datafordeler.dk/<register>/<version>/schema

HTTP-metode

GET

Headere i forespørgsel

Content-Type: application/json

Returværdier

·         Returnerer HTTP 200 – OK, ved succes.

·         Returnerer HTTP 400 – Bad Request, ved angivelse af forkerte parametre.

·         Returnerer HTTP 404 – Not Found, hvis den angivne ressource ikke kan findes.

·         Returnerer HTTP 500 – Internal Server Error, hvis der er sket en ukendt fejl

Adgang

IT-system med API-nøgle, OAuth Shared Secret eller OAuth Certifikat.




Parametre



Navn

Type

Beskrivelse

Obligatorisk

Register

String

Angiver hvilket register det pågældende skema skal hentes for.
Følgende registre kan angives:

  • DAR
  • DAGI
  • BBR
  • DHMOprindelse
  • DHMHoejdekurver
  • MAT
  • EBR
  • FIKSPUNKT
  • DS
  • GEODKV
  • CVR
  • CVR/custom
  • EJF
  • SVR
  • VUR
  • HISTKORT

Ja

Version

String

Angiver hvilken version af datamodellen det pågældende register skal være.

Ja





Returværdier


Denne tjeneste returnerer altid en fil ved HTTP 200 – OK. Filen indeholder et GraphQL-schema med metadata om GraphQL-tjenesten, der beskriver hvilke entiteter der findes for det pågældende register og hvordan data fra disse hentes.




Eksempler på brug af tjenesten


Hent skema for DAGI med versionsnummer v1 ved brug API-nøgle:

  • https://graphql.datafordeler.dk/DAGI/v1/schema?apiKey=placeholderNoegle






Send query


Send query

URL

https://graphql.datafordeler.dk/<register>/<version>

HTTP-metode

GET & POST

Headere i forespørgsel

For POST-requests:

·         Content-Type: application/json

For GET- og POST-requests (valgfrit):

·         Accept: application/graphql-response+json

Body

For GET-requests:

·         Ingen. Query-parametre skal URL-encodes i overensstemmelse med GraphQL-standarden.

For POST-requests:

·         Valid GraphQL-query.

Returværdier

·         Returnerer HTTP 200 – OK, ved succes.

·         Returnerer HTTP 400 – Bad Request, ved angivelse af forkerte parametre.

·         Returnerer HTTP 404 – Not Found, hvis den angivne ressource ikke kan findes.

·         Returnerer HTTP 500 – Internal Server Error, hvis der er sket en ukendt fejl

Adgang

·         Ikke-adgangsbegrænset data: IT-system med API-nøgle, OAuth Shared Secret eller OAuth Certifikat.

·         Adgangsbegrænset data: IT-system med OAuth Shared Secret eller OAuth Certifikat og på en defineret IP-Allowlist og så skal IT-systemet have eksplicit godkendelse fra det pågældende register. Se afsnit 3 for yderligere information.

Bemærk

Du bør som anvender inkludere Accept-headeren som specificeret her, hvis du vil opt-in til moderne GraphQL-over-HTTP. Dette er dog ikke et krav. Hvis Accept-headeren ikke inkluderes fås andre HTTP-statuskoder. 


Bemærk

Returværdierne for HTTP-statuskoderne afhænger af hvilken Accept-header der specificeres. Værdierne i tabellen er hvis Accept-headeren ikke er angivet som beskrevet i ”Headere i forespørgsel”.




Parametre


Navn

Type

Beskrivelse

Obligatorisk

Register

String

Angiver hvilket register det pågældende skema skal hentes for.
Følgende registre kan angives:

  • DAR
  • DAGI
  • BBR
  • DHMOprindelse
  • DHMHoejdekurver
  • MAT
  • EBR
  • FIKSPUNKT
  • DS
  • GEODKV
  • CVR
  • CVR/custom
  • EJF
  • SVR
  • VUR
  • HISTKORT

Ja

Version

String

Angiver hvilken version af datamodellen det pågældende register skal være.

Ja




Returværdier


Denne tjeneste returnerer et json-response ved HTTP 200 – OK.




Eksempler på brug af tjenesten


Hent de første 100 datapunkter fra entiteten DAR_Adresse fra version 1 af DAR inden for den angivet periode ved at sende nedenstående query ved brug af API-nøgle:

  • https://graphql.datafordeler.dk/DAR/v1?apiKey=placeholderNoegle





Hent data der var gældende den 12/11/2024, kl. 14:41:33 med kommunekode “0550” fra entiteten BBR_Bygning fra version 1 af BBR ved at sende nedenstående query som et POST-request  ved brug af API-nøgle:

  • https://graphql.datafordeler.dk/BBR/v1/?apiKey=placeholderNoegle







Autentifikation og autorisation for GraphQL-tjenester


Når du ønsker at benytte GraphQL-tjenester kræver det at anvenderen er autentificeret. Datafordeleren har en række forskellige autentifikationsmetoder, som skal benyttes afhængigt af om du forsøger at tilgå frit tilgængeligt eller adgangsbegrænset data:

  • IT-system med API-nøgle: En API-nøgle er en privat nøgle, som bruges til at autentificere mod et API. Denne nøgle bruges som en del af godkendelsesprocessen, hvor en klient får adgang til et API uden at afsløre brugerens loginoplysninger. Når en API-nøgle er oprettet, bruges API-nøglen som et query-parameter for at tilgå GraphQL-tjenesterne. Bemærk at API-nøgler ikke kan bruges til at tilgå adgangsbegrænsede data. En API-nøgle bruges som query-parameter ved at indsætte den i selve URL’en således: https://graphql.datafordeler.dk/<Register>/<Version>?apiKey=placeholderNoegle
  • IT-system med OAuth Shared Secret: En OAuth Shared Secret er en privat nøgle, som deles mellem en klient (f.eks. en applikation) og udbyderen (f.eks. en service som Datafordeleren). Denne nøgle bruges som en del af godkendelsesprocessen, hvor en klient får adgang til ressourcer på vegne af en bruger uden at afsløre brugerens loginoplysninger. For at blive autentificeret ved hjælp af OAuth Shared Secret skal du som anvender først oprette en Shared Secret Datafordeler Administration. Når du har oprettet en Shared Secret sendes denne, samt Client ID og grant type til https://auth.datafordeler.dk/realms/distribution/protocol/openid-connect/token i en POST-request hvorefter man vil modtage et Access Token. En mere detaljeret beskrivelse af hvordan man får et Access Token kan findes her. Det resulterende token er et Bearer Token der kan bruges til autentifikation ved efterfølgende kald til datafordeleren. Bemærk at dette token kun er validt i 60 minutter efter udstedelsen. 
  • IT-system med OAuth Certifikat: Klientautentificering med certifikater i OAuth er en sikkerhedsmetode, hvor en klient (f.eks. en applikation) bruger et digitalt certifikat til at bevise sin identitet over for autorisationsserveren. Processen involverer, at klienten præsenterer sit certifikat under TLS-håndtrykket, hvorefter autorisationsserveren validerer det. Denne metode er særligt velegnet til miljøer med høje sikkerhedskrav eller ved håndtering af følsomme data. OAuth Certifikater kan bruges i stedet for Oauth Shared Secrets og sættes på kaldet som en client assertion. På samme måde som OAuth Shared Secret, skal certifikatet bruges til at indhente et Access Token. Dette gøres ved at Client ID, samt certifikat til https://auth-oces.datafordeler.dk/realms/distribution/protocol/openid-connect/token i en POST-request. En mere detaljeret beskrivelse af hvordan Access Token indhentes via certifikat kan findes her. Afsnit 3.3 kommer med et eksempel på hvordan man kan opsætte OAuth med certifikater. Bemærk at dette token kun er validt i 60 minutter efter udstedelsen. 

Bemærk

Det er ikke muligt at benytte tjenestebruger til autentifikation for at hente data via GraphQL-tjenesterne.







Access tokens og Shared Secrets


I OAuth er et Access Token en hemmelig nøgle som er med til at identificere en anvender hos Datafordeleren, uden at kende til brugernavn eller et password. Når du laver en query med et Access Token i en Authorization header med et Bearer Token, kan Datafordeleren finde ud af hvilke rettigheder og roller som du har. En query bliver derfor afvist hvis dit Access Token mangler. 

Nedenstående tabel indeholder en beskrivelse af de oplysninger der skal angives for at få udstedt et Access Token.

Client credentials

Beskrivelse

Eksempel på værdi

Client_id

Her skal angives den værdi som fremgår i ”Client ID”-kolonnen i overblikket over OAuth Shared Secret.

00001111-aaaa-2222-bbbb-3333cccc4444

Client_secret

Her skal angives værdien som blev vist da Shared Secret blev oprettet i Datafordeler Administration.

qWgdYAmab0YSkuL1qKv5bPX

Grant_type

Skal altid sættes til “client_credentials”.

client_credentials

 




Når du har modtaget et Access Token, skal det angives i en Authorization header i kaldet til tjenesterne. Nedenstående tabel beskriver hvorledes Access Token angives i kaldet.

HTTP header

Beskrivelse

Eksempel på værdi

Authorization

Her skal angives det Access Token som blev sendt tilbage ved kald til https://auth.datafordeler.dk/realms/distribution/protocol/openid-connect/token. Bemærk at eksemplet er forkortet og at det faktiske Access Token er betydeligt længere.

Bearer eyJhbGciOiJSUzI1NiIsI….







Eksempel på OAuth opsætning i en GraphQL klient


Opsætning med OAuth Shared Secret


Hvis du som anvender ønsker at bruge Shared Secret og Client Id til at sende en query til Datafordelerens GraphQL tjeneste kan du med fordel bruge et program som f.eks. Postman, som understøtter både GraphQL-queries og OAuth-opsætning.

Når OAuth credentials er oprettet i Datafordeler Administration, kan du gå i gang med OAuth-opsætningen i Postman. Her er det vigtigt at du noterer dit Client ID og Shared Secret da disse værdier skal bruges til at hente et Access Token igennem Datafordeleren som blandt andet giver adgang til GraphQL-tjenesten.




1) Åben Postman og klik på ”Collections” i venstre side. Collections er en folder/mappe med et bestemt navn, hvor du kan samle alle dine queries til Datafordeleren og eventuelt navngive dem efter behov.


For at oprette en collection trykker du på ”+” ikonet og vælger ”Blank collection”. Derefter kan du i toppen navngive din collection.




2) Når en collection er oprettet, kan du oprette en request ved at højreklikke på sin collection eller trykke på de 3 prikker og derefter vælge ”Add request”.

Her kan du også navngive din request efter behov.




3) Når requesten er oprettet kan du i HTTP metoden vælge GET, hvis du vil hente et GraphQL-skema, eller POST hvis du vil sende en query.

Dette eksempel tager udgangspunkt i en POST request med OAuth-credentials til BBR.

I feltet til URL’en kan du indsætte https://graphql.datafordeler.dk/BBR/v1 for at kunne lave queries til BBR-version 1.



4) Vælg requesten i venstre side (hvis den ikke allerede er aktiv som i det forrige trin) og klik på ”Authorization” for at skifte til en anden fane. Her skal du vælge ”OAuth 2.0” i ”Auth Type” menuen.

Postman skulle gerne skifte indholdet når du har valgt en ny auth type.



5) Du skal herefter scrolle ned i den aktive ”Authorization” fane indtil du kan se en ”Configure New Token” overskriften. 

Under overskriften vil der være en række felter som skal udfyldes som beskrevet herunder.

    1. I ”Token Name” kan du give din Access Token et passende navn.
    2. I ”Grant type” menuen skal du vælge ”Client Credentials”. Her vil Postman ændre felterne under med dem som relevant for din konfiguration af OAuth.
    3. I ”Access Token URL” skal du indsætte følgende link - https://auth.datafordeler.dk/realms/distribution/protocol/openid-connect/token
    4. I ”Client ID” skal du indsætte det Client ID som de har modtaget efter at have oprettet det i OAuth sektionen på Datafordeler Administration.
    5. I ”Client Secret” skal du indsætte den Shared Secret som du har modtaget efter at have oprettet det i OAuth sektionen på Datafordeler Administration.
    6. Anvenderen kan ignorere ”Scope” feltet, men skal verificere at ”Client Authentication” feltet er sat til ”Send as Basic Auth header”.



6) Efter du har udfyldt de nødvendige felter, kan du hente dit Access Token ved at rulle ned indtil du ser en orange knap der hedder ”Get New Access Token” og klikke på den. 

Derefter vil Postman åbne et vindue som indikerer at applikationen er gået i gang med at hente Access Token fra Datafordeleren.

Når Access Token er hentet, vil Postman opdatere vinduet med et grønt flueben og med teksten ”Authentication complete”. Herefter kan du vente 5 sekunder eller trykke på ”Proceed” knappen i nederste højre hjørne. Herefter vil Postman åbne et nyt vindue.



7) Når Postman har åbnet det næste vindue, vil Access token og dets navn stå under ”Token Details”.

Du kan nu trykke på ”Use Token” til at bruge den til at lave queries i Postman eller kopierer access token til anden applikation.

8) Hvis du trykker på ”Use Token” vil Postman automatisk udfylde det i den request som du oprettede tidligere. Herefter kan du lukke vinduet og klikke på ”Body” fanen, efterfuldt ved at klikke på GraphQL muligheden længst til højre. Til sidst kan du skrive en GraphQL-query til BBR og indsætte det i ”Query” tekstfeltet.




9) Når du er klar til at indsende din query kan du trykke på ”Send” oppe i højre hjørne.


Herefter vil svaret fra GraphQL tjenesten blive vist i bunden.



10) Du er nu klar til at indsende queries til Datafordeleren som bruger OAuth 2.0 Client Id og Client Secret til at autentificere til GraphQL tjenesterne.




Opsætning med OAuth certifikat


Såfremt du skal sætte Postman op med OAuth certifikat, skal du sætte OAuth 2.0-indstillinger op, samt vedhæfte et certifikat i Postman.

Fremgangsmåden er næsten den samme som beskrevet under eksemplet med Shared Secret, dog med få forskelle. Fremgangsmåden er som følger:


1) Punkt 1-4 følges, som de er beskrevet ovenfor under eksemplet med Shared Secret.




2) Herefter skal OAuth 2.0-indstillinger opsættes for certifikatet. Gå ind under ”Authorization” i requesten, og scroll ned til ”Configure New Token”.

Under overskriften vil der være en række felter som skal udfyldes som beskrevet herunder.

a. I ”Token Name” kan du give din Access Token et passende navn.

b. I ”Grant type” menuen skal du vælge ”Client Credentials”. Her vil Postman ændre felterne under med dem som relevant for din konfiguration af OAuth.

c. I ”Access Token URL” skal du indsætte følgende link - https://auth-oces.datafordeler.dk/realms/distribution/protocol/openid-connect/token.

d. I ”Client ID” skal anvenderen indsætte det Client ID som de har modtaget efter at have oprettet det i OAuth sektionen på Datafordeler Administration.

e. Du kan ignorere ”Scope” feltet, men skal verificere at ”Client Authentication” feltet er sat til ”Send client credentials in body”.




3) Vælge ”Settings” oppe i højre hjørne:



4) Vælg herefter ”Add Certificate”.



5) Angiv herefter ”host” og certifikatet.

    1. Host skal være https://auth-oces.datafordeler.dk.
    2. PFX file skal pege på certifikatet som indeholder den private nøgle. Det er vigtigt at dette certifikat stemmer overens med det certifikat som blev uploadet inde i portalen.
    3. Passphrase skal stemme overens med password til certifikatet.
    4. Bemærk at det kan være nødvendigt at installere ”Den Danske Stat” rodcertifikatet på anvenders maskine for at maskinen stoler på det certifikat der er vedhæftet inde i Postman.



6) Punkt 6-10 følges, som de er beskrevet ovenfor under eksemplet med Shared Secret.