Dit document beschrijft een API strategie voor de Nederlandse overheid.
Deze paragraaf beschrijft de status van dit document ten tijde van publicatie. Het is mogelijk dat er actuelere versies van dit document bestaan. Een lijst van Geonovum publicaties en de laatste gepubliceerde versie van dit document zijn te vinden op https://www.geonovum.nl/geo-standaarden/alle-standaarden.
Dit is een definitief concept van de nieuwe versie van de handreiking. Wijzigingen naar aanleiding van consultaties zijn doorgevoerd.
Dit onderdeel is niet normatief.
Dit hoofdstuk geeft een inleiding op de Nederlandse API strategie
In deze versie van de API strategie zijn de op en aanmerkingen uit de consultatie verwerkt. Op GitHub kan bekeken worden wat er precies is gedaan met de op en aanmerkingen.
Er worden slechts 6 auteurs genoemd, echter aan deze strategie is door veel meer mensen gewerkt. De genoemde auteurs zijn de 6 trekkers van de 5 werkgroepen API Strategie, Architectuur, Authenticatie en Autorisatie, Communicatie en Beleid, en Gebruikerswensen
Dit document bevat twee delen, waarbij het eerste deel "niet-technisch" en het tweede deel "technisch" van aard is. In het eerste deel zitten de hoofdstukken Communicatie en Beleid en Gebruikerswensen.
Het tweede deel bevat de hoofdstukken API designrules, Beveiliging en Architectuur, waarin een technische uitwerking van de eerste twee hoofdstukken staat.
De hoofdstukken API designrules en de API Principes zijn Engelstalig, want deze zijn gericht op de (internationale) developer community. In paragraaf Extensies in het hoofdstuk API designrules staan links naar de gepubliceerde en werkversie van het aparte document met extensies.
Dit onderdeel is niet normatief.
Dit hoofdstuk geeft een niet-technische inleiding voor bestuurders en managers. In dit hoofdstuk bekijken we:
- welk probleem willen we oplossen?
- wat zijn APIs en hoe helpen ze bij dit probleem?
- wanneer zijn APIs relevant voor mijn organisatie?
- voorbeelden van het gebruik van APIs in Nederland
Larissa gaat verhuizen van Den Haag naar Amsterdam. Ze gaat naar het gemeentehuis in Amsterdam om zich in te schrijven. Achter de schermen komt er een ingewikkelde gegevensstroom op gang.
Amsterdam en Den Haag houden elk hun eigen registratie van personen bij. De ICT systemen van Amsterdam moeten daarom de persoonsgegevens van Larissa opvragen bij de ICT systemen van Den Haag. Daarna kan Amsterdam Larissa in z’n eigen basisregistratie personen registreren. De gemeente Den Haag moet weten dat Larissa nu in Amsterdam staat ingeschreven. Dus stuurt Amsterdam verwijsgegevens voor Larissa naar Den Haag. Den Haag verwerkt de verwijsgegevens voor Larissa in z’n lokale basisregistratie personen. Zowel Amsterdam als Den Haag moeten de mutaties van hun lokale basisregistratie personen ook nog doorgeven aan de centrale basisregistratie personen van de Autoriteit Persoonsgegevens (BRP). Zo kan het drie werkdagen kosten om een eenvoudige verhuizing volledig te registreren.
Is het niet efficiënter om één basisregistratie personen bij te houden, in plaats van gegevens heen en weer te schuiven van de ene lokale registratie naar de andere?
Bij veel ICT systemen van de overheid zitten de gegevens (de data) helemaal verweven in de applicatie. Ieder systeem heeft z'n eigen database en kopieert data van en naar andere systemen. Zo werken veel systemen bij gemeenten met kopieën van de landelijke basisregistraties. Met de jaren ontstaat daardoor een wirwar aan koppelingen tussen systemen.
Bron: VNG Realisatie.
De huidige situatie brengt een aantal problemen met zich mee:
We kunnen de digitale overheid veiliger, efficiënter en beter beheersbaar maken door applicaties beter te scheiden van de gegevens en de gegevens alleen bij de bron te bewaren. Door de gegevens alleen door de bronhouder te laten beheren, hoeven ze niet meer op grote schaal gekopieerd, gedupliceerd en gesynchroniseerd te worden. Dit idee zit achter het nieuwe gegevenslandschap met als onderdelen Haal Centraal en Common Ground.
Dit vraagt om technologie waarmee je gegevens op een betrouwbare en schaalbare manier kan ontsluiten bij de bron. Dat kan met APIs.
Een application programming interface (API) is een gestructureerd en gedocumenteerd koppelvlak voor communicatie tussen applicaties. Je kan een API zien als een digitale stekkerdoos die applicaties met elkaar verbindt. APIs bestaan al zo lang er computers zijn.
Hier hebben wij het in het bijzonder over APIs waarmee je applicaties over het Internet kan koppelen. Zogenaamde REST APIs doen voor applicaties wat websites voor mensen doen. Websites presenteren informatie aan mensen, REST APIs maken applicaties en gegevens over het Internet beschikbaar voor andere applicaties. De technologie achter websites en REST APIs heeft daarom veel gemeen.
De meeste applicaties gebruiken APIs onder de motorkap zonder dat de eindgebruiker dat ziet. Als je een app opent voor het weer, dan merk je niet dat deze app gegevens ophaalt bij het KNMI via een API. Degene die het meest direct met een API te maken krijgt is de ontwikkelaar van de applicatie die de API gebruikt. Zij moet begrijpen hoe de API werkt en hoe je deze vanuit de applicatie moet bevragen.
Hier verschillen APIs dus van websites. Een website bouw je voor de eindgebruiker die hem bezoekt. Een API maak je voor programmeurs die er applicaties mee bouwen. Daarom is het gewoonte om APIs aan te bieden op het developer subdomein van een website, zoals developer.overheid.nl voor APIs van de overheid.
APIs zijn een middel, geen doel. De missie van een organisatie bepaalt of APIs toegevoegde waarde hebben in de ICT processen. Dat kan het geval zijn als de organisatie een dienstverlenende taak heeft en gegevens beheert die andere organisaties gebruiken. Of als de organisatie deel uit maakt van een of meer ketens.
Een aantal zaken om te overwegen:
Inventariseer welke gegevens je organisatie voortbrengt en welke gegevens je gebruikt van andere organisaties. Bekijk hoe de bestaande ICT koppelingen ingericht zijn. Is je organisatie daarbij afhankelijk van bepaalde producten of leveranciers? Kan het efficiënter, flexibeler, veiliger en meer open met APIs?
Deze API strategie beschrijft de standaarden, ontwerpprincipes en veiligheidsmaatregelen die ervoor zorgen dat alle overheden hun APIs op een inzichtelijke, gebruikersvriendelijke, veilige en geharmoniseerde manier aanbieden. Door deel te nemen in het Kennisplatform APIs krijgt je organisatie meer inzicht in de toegevoegde waarde die APIs voor jouw toepassing al dan niet kunnen bieden.
Veel publieke organisaties in Nederland bieden hun gegevens met APIs aan. De Nederlandse Spoorwegen bijvoorbeeld, die met APIs actuele vertrektijden, prijzen, storingen en reisadviezen publiceren om in apps te gebruiken. En de Rijksdienst voor het Wegverkeer die de kentekenregistratie voor voertuigen met een API aanbiedt.
In februari 2019 won de Basisregistratie Adressen en Gebouwen (BAG) API van Kadaster de Gouden API die het Kennisplatform APIs uitloofde voor de beste API van de overheid. De BAG registreert voor elk adres in Nederland gegevens als de geografische coördinaten, het bouwjaar van het pand, de oppervlakte en het vergunde gebruiksdoel. Verzekeraars, hypotheekverstrekkers, hulpdiensten, milieudiensten en vele anderen gebruiken informatie uit de BAG. Dat de BAG API voldoet aan een behoefte blijkt wel uit de 300 miljoen consultaties die de BAG API in 2018 verwerkte.
De APIs van Luchtmeetnet en van de Kamer van Koophandel kregen bij de Gouden API eervolle vermeldingen vanwege hun relevantie en gebruiksgemak. De API van de Kamer van Koophandel geeft applicaties toegang tot de gegevens van het handelsregister. Hiermee kunnen bijvoorbeeld bedrijven en gemeenten CRM systemen, zaaksystemen en factureringssystemen aan het handelsregister koppelen. De API van Luchtmeetnet geeft bijvoorbeeld weer-apps de mogelijkheid om ook informatie over luchtkwaliteit voor astmatici te geven.
Het portal developer.overheid.nl geeft een overzicht van APIs die Nederlandse overheidsorganisaties aanbieden. Heeft jouw organisatie gegevens waar bedrijven, burgers of andere overheden iets mee kunnen?
Dit onderdeel is niet normatief.
Overheden bezitten kwalitatief hoogwaardige data en bieden deze aan via API’s. Vanuit het open data-perspectief maken overheden het hiermee mogelijk dat anderen -binnen én buiten de overheid- zinvolle toepassingen kunnen ontwikkelen, die maatschappelijke meerwaarde bieden. Maar de overheid gaat nog verder: bij initiatieven als Common Ground is het gebruik van API’s zelfs randvoorwaardelijk om werkprocessen zodanig in te richten, dat data altijd bij de bron bevraagd en gewijzigd kan worden. Een belangrijke succesfactor in deze ontwikkelingen is de mate waarin overheden erin slagen om drempels voor het gebruik van hun API’s weg te nemen. Om het gebruik zo laagdrempelig mogelijk te maken, is het essentieel dat er aandacht is voor de wensen van gebruikers. En om te begrijpen welke wensen ze hebben, is het essentieel om te begrijpen wie die gebruikers zijn. In generieke zin zijn de gebruikers van API's developers: mensen die toepassingen ontwikkelen. Deze developers fungeren als intermediair tussen de data- of dienstaanbieder enerzijds en de eindgebruiker anderzijds. Neem bijvoorbeeld een gemeente die het mogelijk wil maken dat burgers makkelijk melding kunnen maken van een defecte lantarenpaal, losliggende stoeptegel of zwerfvuil, De burger is dan de eindgebruiker, maar de ontwikkelaar van de Melding Openbare Ruimte app is de gebruiker van de API's die de gemeente aanbiedt om bijvoorbeeld een kaartondergrond op te halen of een melding aan te bieden aan de gemeente. De gebruikerswensen liggen niet alleen op het “wat” (wat voor data krijg ik?), maar zeker ook op het “hoe” (hoe makkelijk kan ik aan de slag met deze API?). Bij de eerste kennismaking met de API moet de gebruiker verleidt worden om de API te gaan gebruiken en in alle volgende fases van gebruik (implementeren, in productie nemen en in productie houden) moet de gebruikerservaring zodanig zijn, dat de gebruiker geen enkele reden heeft om af te haken. Sterker nog: idealiter wordt de gebruiker zó enthousiast over de API en de bijbehorende ondersteuning, dat de gebruiker onderdeel wordt van de gebruikerscommunity en actief gaat bijdragen aan verdere ontwikkeling en promotie van die API. Merk op dat dit effect alleen bereikt kan worden, wanneer de totaalbeleving klopt: ook al is het product (de data) zelf nog zo goed, als de gebruikservaring belabberd is, dan zul je niet veel potentiële gebruikers verleiden om met je data zinvolle toepassingen te gaan ontwikkelen. En nog erger: gebruikers die tóch met de API aan de slag gaan, zullen de helpdesk van de aanbieder zwaar gaan belasten, de data mogelijk verkeerd gaan interpreteren en de ICT-infrastructuur onnodig zwaar belasten, wanneer zij slechts omslachtig (met veel API-calls) de gewenste gegevens kunnen krijgen.
De belangrijkste aanbeveling aan aanbieders van API’s is om zich te richten op die gebruikservaring; op een goede ‘developer experience (DX)’. Goede DX komt voort uit stapeling van aandacht voor functionality (functionaliteit - wat moet de API doen?), voor usability (hoe bruikbaar is de API voor de developer?) en daar bovenop voor de experience (hoe voelt de developer zich als die de API gebruikt?). Dat laatste aspect -hoe voelt de developer zich- klinkt wellicht wat vaag, maar het is in essentie de optelsom van ervaringen in de interactie tussen een developer en een API aanbieder. Stel: een developer, Johan (26 jaar – ZZP-er), heeft moeite om een bepaalde API te vinden, vervolgens blijkt het registratieproces lastig en krijgt hij de API key pas een week later, daarna blijkt de documentatie in voor Johan deels onbegrijpelijk jargon geschreven (én is het ook nog eens een PDF van 352 pagina’s), dan heeft Johan meerdere calls nodig om de gewenste data te krijgen en uiteindelijk is data helemaal niet in het door Johan gewenst formaat. Elke kleine irritatie is op zichzelf niet onoverkomelijk, maar de optelsom maakt dat Johan concludeert: “Dit is niet te doen, ik zoek wel wat anders!”.
De zwakte van veel teksten over ‘developer experience’ is dat men zich vaak alleen richt op de use case van een technische developer die een API wil implementeren - denk aan Johan in de vorige paragraaf. Gebruik begint echter niet bij de poging tot implementatie; hier gaan nog stappen aan vooraf. Johan heeft zich al een aantal vragen gesteld, voordat hij besloot om die poging te wagen. Die vragen -en daarmee de stappen die hij doorloopt- zijn beter te introduceren aan de hand van het voorbeeld van een grotere softwareleverancier. Stel: Anne (43 jaar) werkt als product manager bij een commerciële softwareleverancier en heeft een aantal applicaties voor de gemeentelijke markt in haar portfolio. Ze ziet een API op een ontwikkelaarsportaal en beoordeelt aan de hand van de functionele specificaties of implementatie van de API meerwaarde biedt voor één van haar applicaties. Eén API trekt haar aandacht en Anne vraagt Steven (56 jaar, architect bij hetzelfde bedrijf) om te beoordelen of de API past binnen de software stack van het bedrijf en kritisch te kijken naar eventuele security en privacy issues. Steven ziet mogelijkheden en vervolgens krijgt Jeffrey (37 jaar, software engineer bij hetzelfde bedrijf) de opdracht om binnen een dag te beoordelen of hij de API succesvol kan integreren in de nieuwe versie van het product uit Anne’s portfolio. Na Jeffrey’s positieve oordeel besluit Gea, de manager, om tijd en geld vrij te maken voor implementatie. Zo komt de API uiteindelijk in de productieversie terecht: *"developer tries, business buys"*.
Dit eindresultaat is bereikt, doordat in alle fases de ‘onboarding’ -het proces dat Anne, Steven en Jeffrey doorliepen toen zij voor de eerste keer gebruik maakten van een digitale service (het aanbieden van de API)- prettig verliep. Uit marketingonderzoeken blijkt een prettige eerste gebruikerservaring van een online platform (bijvoorbeeld het ontwikkelaarsportaal waarop Anne de API ontdekte en zij vervolgens samen met Steven en Jeffrey de API beoordeelde) veel invloed heeft op het verdere gebruik ervan. Oftewel: de kans is groot dat dit bedrijf vervolgens ook andere API’s op dit ontwikkelaarsportaal gaat gebruiken.
De kern van dit verhaal is dat een API technisch gezien weliswaar een machine tot machine koppeling is, maar strategisch juist gezien moet worden als een product. En dat product moet gebruikers (zie ze als potentiële klanten!) verleiden tot gebruik. Dan zijn aspecten als de winkelervaring (in een API store of ontwikkelaarsportaal), de geboden service en de kwaliteit van het product de doorslaggevende factoren in de beslissing om tot gebruik over te gaan.
Een API is weliswaar een machine tot machine koppeling, maar onthoud: API's ontwerp en bouw je niet voor een machine, maar voor een gebruiker: een mens! Om een goede DX te bieden, moet je dus eerst weten voor wie je ontwerpt en bouwt, voordat je dat goed kunt doen. Persona’s zijn dan belangrijk, er is niet maar één type developer! Redeneer van buiten naar binnen: wie zijn mijn gebruikers, wat willen zij kunnen doen en wat moet ik doen om dat zo goed mogelijk te faciliteren. Het typeren van gebruikers en analyseren welke behoeften zij hebben, doe je op basis van persona’s.
Belangrijk hierbij is om te onderkennen dat er verschillende niveaus of typen gebruik zijn. Onderscheid daarom -met de fases van ‘onboarding’ tot ‘in productie’ in het achterhoofd- minimaal de volgende persona’s:
een product manager / business developer: focus op het kunnen beoordelen van functionaliteit (“Is dit relevant voor mijn product / mijn doel?”)
een architect: focus op het beoordelen van het informatiemodel (“Hoe integreert dit met de rest van onze software?”) en security- en privacy-aspecten.
een technische developer: focus op het daadwerkelijk kunnen gebruiken (“Hoe krijg ik dit werkend?”).
De ene API is de andere niet. In veel modellen worden API’s in drie categorieën onderverdeeld: de System API (die werkt op het niveau van de databron), de Process API (die doet aan orchestration door één of meerdere System API’s aan te roepen) en de Convenience of Experience API (die één specifieke gebruikersvraag beantwoord). Vraag je altijd af welke informatievragen de gebruiker heeft – in veel gevallen hangen deze vragen niet 1:1 samen met het datamodel.
Stel dat je de Basisregistratie Adressen en Gebouwen wil ontsluiten. De informatievraag “Geef me het volledige adres bij deze postcode” is alleen te beantwoorden door intern bij een Verblijfsobject de Openbare Ruimte naam, Nummeraanduiding en Woonplaats op te vragen en te combineren tot één adressering. Bij een System API moet je meerdere calls doen om dit adres op te bouwen, terwijl een Convenience API deze gangbare (maar complexe) vraag in één call kan beantwoorden. Het aanbieden van Convenience API’s naast System API’s is dus erg gebruiksvriendelijk: de 80% gebruikers die hiermee geholpen zijn, confronteer je met slechts 20% van de complexiteit. Vergelijk dit met de Toptaken-aanpak bij de websites van veel gemeenten: de meest aangevraagde producten (bijv. nieuw paspoort en rijbewijs) staan pontificaal op de homepage, terwijl de minder vaak gevraagde diensten op vervolgpagina’s staan. Zo reduceer je de complexiteit voor een zo groot mogelijk deel van je gebruikers.
Elk type gebruiker dat in aanbeveling 1 wordt genoemd (business developer, architect, technische developer) verdient zijn eigen ‘Getting started’ documentatie, gericht op het snel kunnen beoordelen en/of toepassen. Documentatie is nooit een lijvig document (wanneer veel documentatie nodig lijkt, is de functionaliteit vermoedelijk te complex) én nooit een PDF: laat je gebruikers makkelijk klikken naar relevante onderdelen binnen én buiten de documentatie! Referentie-implementaties kunnen ook zinvol zijn om snel een indruk te bieden van functionaliteit. Voor de technische developer is de documentatie conform de Open API Specifiction 3.0 (OAS 3); deze staat in Nederland op de ‘Pas toe of leg uit-lijst’ van het Forum Standaardisatie.
Zorg dat een developer snel een werkend voorbeeld heeft. Dit vraagt om een goed gedocumenteerde, realistische Sandbox: een experimenteeromgeving met testdata. Deze Sandbox dient alle aspecten van de API te ondersteunen en identiek gedrag aan de productieversie van de API te vertonen, bijvoorbeeld rond authenticatie. Daar waar mogelijk is het zeer wenselijk dat meerdere API’s dezelfde dataset bieden als Sandbox, zodat ook het samenspel tussen verschillende API’s getest kan worden.
Ook al is een API nog zo goed ontwikkeld, wanneer doorontwikkeling en beheer niet goed geregeld is, zal die API niet succesvol zijn. Essentieel hierin is dat je gebruikers duidelijkheid biedt:
Maak duidelijk welke verwachtingen een gebruiker mag hebben qua uptime, service window, beprijzing etc.
Maak duidelijk of en zo ja, wanneer er eventuele wijzigingen te verwachten zijn en hoe lang de API minimaal beschikbaar blijft.
Borg dat de toepassing van de gebruiker blijft werken, door te zorgen voor backward compatability. Grotere updates kunnen als nieuwe versie worden uitgebracht, waarbij oudere versies nog een gegarandeerde periode beschikbaar blijven. Het versienummer kan in elke call staan, bijv. GET /api/v1.0/... En versiebeheer slaat niet alleen op de API zelf, maar ook op de bijbehorende documentatie, Sandbox, etc.
Om echt van buiten naar binnen te kunnen werken, is het betrekken van de community van gebruikers onmisbaar. De community kan vertellen hoe de developer experience tot nu toe is, welke verbeteringen wenselijk zijn, welke gebruikersvragen er sterk leven, maar nog onvoldoende ondersteund worden, etc., etc. Daarnaast wil je de community ook actief informeren over voorgenomen wijzigingen e.d. Het gebruik van API keys is een manier om je gebruikers te kennen.
Wanneer je data openstelt voor derden, inclusief niet-specialisten, is het essentieel om eenduidig vast te leggen wat de data betekent, waarbij deze betekenis ook voor niet-specialisten begrijpelijk is. Het vastleggen van semantiek kan o.a. door definities en informatiemodellen goed online te ontsluiten (zoals bijvoorbeeld in de Stelselcatalogus Omgevingswet), maar ook door praktischere zaken als heldere naamgeving van variabelen etc.
Een goede, gebruiksgerichte API, die bovendien actief wordt beheerd en doorontwikkeld, kan nog steeds weinig gebruikt worden wanneer deze API niet goed vindbaar is. Zorg daarom dat je een goed developersportaal hebt, nationaal idealiter bij developer.overheid.nl. Als een API een product is, hoort dat product ook in een goede winkel te staan. En in een succesvolle winkel is altijd goed nagedacht over productpresentatie: presenteer breed toepasbare API’s en datasets prominenter dan specifiekere API’s en obscure datasets, wederom te vergelijken met de toptaken-aanpak bij gemeentelijke websites. Een goed developersportaal informeert niet alleen over beschikbare API’s, maar inspireert en verleidt zelfs developers om bepaalde API’s te gebruiken. Het vullen van het developersportaal mag daarom nooit sluitpost van een project zijn. Formuleer hierbij ook goed het ambitieniveau:
API store: de one-stop-shop, waarin je niet alleen (het bestaan van) de API ontdekt, maar ook de documentatie vindt, de API kunt uitproberen, etc. Het runnen van een API store kan zelfs zover gaan, dat er centraal proxy's worden ontwikkeld op API's van andere aanbieders en documentatie geredigeerd, om zo voor de eigen gebruikers een zo uniform mogelijke gebruikerservaring te garanderen.
API catalogus: uitsluitend gericht op het ontdekken van API's, waarna doorverwezen wordt naar de API store van de desbetreffende aanbieder.
hybride oplossing: een combinatie van een catalogus en een store. Alle API's staan in de catalogus, een kleine subset (de high-value API's) wordt volledig aangeboden. Deze hybride oplossing zou een mooi ambitieniveau voor developer.overheid.nl kunnen zijn: alle overheids-API's zijn vindbaar en voor de meest generieke en populaire API's ben je direct op de juiste plaats.
Een bijzondere categorie die de overheid ook nodig gaat hebben, o.a. door de ontwikkelingen in Common Ground, is de API spec store: een plaats waarin API specificaties gepubliceerd kunnen worden. Leveranciers kunnen op basis van die specificaties zelf hun specificatie-conforme API's ontwikkelen, waarmee de interoperabiliteit van gegevens binnen het gemeentelijke applicatielandschap wordt vergroot.
In de context van API stores en API catalogi is het belangrijk om te realiseren dat developer experience niet alleen een externe focus heeft (gericht op laten ontdekken, evalueren, testen en gebruiken van API's), maar ook een interne focus, gericht op het activeren van potentiële API-aanbieders. Zij moeten getriggerd worden om API's te ontwikkelen, te ontsluiten in je API store of catalogus, te beschrijven conform bepaalde kwaliteitseisen, etc.
Bedenkt altijd goed of een API de juiste oplossing is. In sommige gevallen is een bulk download nog steeds praktischer voor een gebruiker. Wanneer een API zinvol is? Hoe hoger de mutatiefrequentie van de data, hoe zinvoller een API wordt. En bij hoge mutatiefrequenties, is een API die was-wordt leveringen kan bieden zinvol. Denk hierbij weer aan 'API als een product': ga niet blind data ontsluiten, maar begin bij de vraag welke propositie je neer wil zetten.
This chapter aims to describe a set of design rules for the unambiguous provision of RESTful APIs (henceforth abbreviated as APIs). This achieves a predictable governments so developers can easily start consuming and combining APIs. Until now, this chapter does not include rules for other types of APIs, e.g. SOAP. In the addendum *API-principles, the set of rules has been condensed into a number of core principles to keep in mind for the design and creation of APIs.*
More and more government organisations implement and provide RESTful APIs. In many cases, these APIs provide access to data sets complementary to existing interfaces, e.g. SOAP and WFS. These APIs aim to be developer-friendly (see also paragraph 2.6 and chapter 3) and quick to implement. While this is a commendable aim, it does not shield a developer from a steep learning curve getting to know every new API. A developer has to understand how every API can be used, but there should have to not be a difference in the technical implementation. The Knowlegde Platform APIs aims to provide a set of design rules or prinicples for APIs to align their technical operation across government organisations and to facilitate their implementation. This chapter describes the widely applicable set of design rules. Hopefully, government organisations will adopt these design rules in their own API strategies and provide feedback about exceptions and additions to subsequently improve these design rules.
Keep in mind, these design rules should be applied in the creation of an API only if the functionality described is desirable.
All paragraphs in this chapter, except for paragraph 4.5 are Normative. Paragraph 4.5 is Informative.
The most important prinicple of REST is the seperation of the API in logical resources (things). The resources describe the information of the thing. These resources are manipulated using HTTP-requests and HTTP-operations. Each operation (GET
, POST
, PUT
, PATCH
, DELETE
) has a specific meaning.
HTTP also defines operations, e.g.
HEAD
,TRACE
,OPTIONS
enCONNECT
. In the context of REST, these operations are hardly ever used and have been excluded from the rest of this chapter.
Operation | CRUD | Description |
---|---|---|
POST |
Create | Create resources that represent collections (i.e. POST adds a resource to a collection). |
GET |
Read | Retrieve a resource from the server. Data is only retrieved and not altered. |
PUT |
Update | Replace a specific resource. Is also used as a create " if the resource at the indicated identifier/URI does not exist yet. |
PATCH |
Update | Partially modify an existing resource. The request contains the data that have to be changed and the operations that modify the resource in the designated JSON merge patch format (RFC 7386). |
DELETE |
Delete | Remove the specific resource. |
For each operation one has to specify whether it has to be safe and/or idempotent. This is important, because clients and middelware rely on this.
Safe (read-only)
Safe (read-only) in this case means that the semantics has been defined as read-only. THis is important, because clients and middelware like to use caching.
Idempotent
Idempotent means that multiple, identical requests have the same effect as one request.
Operation | Safe | Idempotent |
---|---|---|
POST |
No | No |
GET , OPTIONS , HEAD |
Yes | Yes |
PUT |
No | Yes |
PATCH |
No | Optional |
DELETE |
No | Yes |
REST makes use of the client stateless server design principle derived from client server with the additional constraint that it is not allowed to maintain the state at the server. Each request from the client to the server has to contain all information required to process the request without the need to use state-information at the server.
API principle: do not maintain state information at the server
A fundamental concept in every RESTful API is the resource. A resource is an object with a type, attributes, relation with other resources and a number of operations to modify them. Resources are referred to using nouns (not verbs) that are relevant from the perspective of the user of the API. Operations are actions applied to these resources. Operations are referred to using verbs that are relevant from the perspectie of the user of the API.
One can translate internal data models as-is to resources, but not by definition. The point is to not hide all relevant implementation details. Some example resources are: aanvragen (applications), activiteiten (activities), panden (buildings), rijksmonumenten (national monuments), and vergunningen (permits).
Once the resources have been identified, one determines the operation that are applicable and how the API supports them. RESTful APIs perform CRUD (Create, Read, Update, Delete) operations using HTTP operations:
Request | Description |
---|---|
GET /rijksmonumenten |
Retrieves a list of national monuments |
GET /rijksmonumenten/12 |
Retrieves a specific national monument |
POST /rijksmonumenten |
Creates a new national monument |
PUT /rijksmonumenten/12 |
Modifies national monument #12 completely |
PATCH /rijksmonumenten/12 |
Modified national monument #12 partially |
DELETE /rijksmonumenten/12 |
Deletes national monument #12 |
REST applies existing HTTP operations to implement functionality at one service endpoint. This removes the requirement for additional URI naming conventions and the URI structure remains clear.
API principle: Leave off trailing slashes from API endpoints
Since the exacy meaning of concepts are often lost in translation, resources are the underlying entities and attributes are defined in Dutch.
API principle: Define interfaces in Dutch unless there is an official English glossary
Here, the Keep It Simple Stupid (KISS) rule is applicable. Although grammatically, it may feel wrong to request a single resource using the plural of the resource, it is a pragmatic choice to refer to endpoints consistently using plural. For the user it is much easier to not have to keep in mind singular and plural (aanvraag/aanvragen, regel/regels). Furthermore, this implementation is much more straightforward as most development frameworks are able to resolve both a single resource (/aanvragen/12
) and multiple resources (/aanvragen
) using one controller.
If a relation can only exist in the contexst of another resource (1 to n relation), then the dependent resource (child) can only be retrieved through the parent. The next example explains this. A status belongs to one application. Statuses can be retrieved through the endpoint /aanvragen
:
Request | Description |
---|---|
GET /aanvragen/12/statussen |
Retrieves a list of statuses of application #12 |
GET /aanvragen/12/statussen/5 |
Retrieves a specific status (#5) of application #12 |
POST /aanvragen/12/statussen |
Creates a new status for application #12 |
PUT /aanvragen/12/statussen/5 |
Modifies status #5 of application #12 completely |
PATCH /aanvragen/12/statussen/5 |
Modifies status #5 of application #12 partially |
DELETE /aanvragen/12/statussen/5 |
Deletes status #5 of application #12 |
API principle: Create relations of nested resources within the endpoint
In case of an n-to-n relation, there are various ways to retrieve a resource. The following requests respond identically:
Request | Description |
---|---|
GET /aanvragen/12/activiteiten |
Retrieves a list of activities for application #12 |
GET /activiteiten?aanvraag=12 |
Retrieves a list of activities, filtered by application #12 |
In case of an n-to-m relation, the API supports the retrieval of individual resources anyway, at least providing the identifier of the related resource (relation). The user has to request the endpoint of the related resource (relation) to retrieve this one. This is referred to as lazy loading. The user decides whether to load the relation and when.
The user of an API does not alway require the complete representation (i.e. all attributes) of a resource. Providing the option to select the required attributes in the requests reduces network traffic (relevant for light-weight applications), simplifies the use of the API and makes it adjustable (fit-for-use). The query parameter fields
supports this usage. The query parameter accepts a comma-separated list of field names. The result is a custom representation. For example, the following request retrieves sufficient information to show a sorted list of applications (aanvragen):
In the case of HAL, linked resources are embedded in the default representation. Applying the aforementioned fields
parameter, the contents of the body can be customised as required.
GET /aanvragen?fields=id,onderwerp,aanvrager,wijzigDatum&status=open&sorteer=wijzigDatum
There are resource operations that are not related to data manipulation (CRUD). Examples of this kind of operations are: changing the state (activate and deactivate) of a resource and marking (starring) a resource. Depending on the type of operation there are three approaches:
Restructure the operation to incorporate it into the resource. This approach applies if the operation does not require any parameters. For example, an activation operation can be assigned to a boolean field geactiveerd
that can be modified by a PATCH
to the resource.
Treat the operation as a sub-resource. For example, mark an application by PUT /aanvragen/12/markeringen
and remove a mark by DELETE /aanvragen/12/markeringen
. To fully follow the REST principles, also provide the GET
operation for this sub-resource.
Sometimes there is no logical way to link an operation to an existing resource. An example of this kind of operations is a search across multiple resources. This operation cannot be assigned to anyone specific resource. In this case, the creation of an independent service endpoint /_zoek
is the most obvious solution. Use the imperative mood of a verb to distinguish these endpoints from genuine endpoints that use the indicative mood of a verb.
The Dutch API strategy prefers approach 2 and 3.
API principle: Implement operations that do not fit the CRUD model as sub-resources
An API is as good as the accompanying documentation. The documentation has to be easily findable, searchable and publicly accessible. Most developers will first read the documentation before they start the implementation. Hiding the documentation in PDF documents and/or behind a login creates a barrier not only for developers but also for search engines. Specifications (documentation) are avaialble as Open API Specification (OAS) v3.0 or newer.
The documentation should provide examples including full request and response cycles. Developers should be able to test (and perform) requests directly from within the documentation. Furthermore, each error should be described and labeled with a unique error code to trace errors.
Once an API is in production, the contract (interface) should not be changed without prior notice. The documentation should include a deprecation schedule and all details of the change. Changes should be published not only as a changelog on a publicly available blog but also through a mailing list, using the email addresses obtained when the API keys were issued.
API principle: Include a deprecation schedule when publishing API changes
APIs should always be versioned. Versioning facilitates the transition between changes. Old and new versions are offered during a limited (1 year) transition period. A maximum of 3 versions of the API should be supported. Users decide themselves the moment they transition from the old to the new version of an API, as long as they do this prior to the end of the transition period.
API principle: Allow for a (maximum) 1 year transition period to a new API version
Provide old and new versions (maximum 3) of an API concurrently for a limited, maximum 1 year transition period.
The URI of an API should include the major version number only. This allows the exploration of multiple versions of an API in the browser.
The version number start at 1 and is raised with 1 for every major release that breaks the backwards compatibility of the interface. The minor and patch version numbers are always in the response header of the message in the major.minor.patch
format.
The header (both request and response) should be implemented as follows:
HTTP header | Description |
---|---|
API-Version |
Indicates a specific API version in the context of a specific request. For example: API-version: 1.2.56 |
Using an optional request header one minor/patch version can be addressed. This means, that the client can send a request header to not only access versions v1 and v2 (the designated versions that are addressed in the URIs) but also access one older or newer version of API in the (pre-) production or acceptance test environment. For example, the following URIs point to the designated production release of the API that can be accessed in the URI:
https://service.omgevingswet.overheid.nl/publiek/catalogus/api/raadplegen/v1
API-version: 1.0.2
(response header)
https://service.omgevingswet.overheid.nl/publiek/catalogus/api/raadplegen/v2
API-version: 2.1.0
(response header)
Leaving off the request-header (API-version: x.y.z
), one addresses always the designated production version. In case there is one other designated version available, e.g. v2.1.1, then it can be provided and addressed at the same base endpoint passing the correct request parameter:
API-version: 2.1.1
(request header)
https://service.omgevingswet.overheid.nl/publiek/catalogus/api/raadplegen/v2
API-version: 2.1.1
(response header)
Examples of backward compatible changes are the addition of an endpoint or an optional attribute to the payload.
API principle: Include only the major version number in the URI
One should only include the major version number. Minor version number and patch version number are included in the header of the message. Minor and patch versions have no impact on existing code, but major version do.
An API will never be fully stable. Change is inevitable. Managing change is important. In general, well documented and timely communicated deprecation schedules are the most importand for API users.
More about extensions (in Dutch only).
Dit onderdeel is niet normatief.
Er is een gepubliceerde versie en een werkversie van het document met extensies. De Werkversie staat op github en is het document dat "under construction" is, en dus de allerlaatste aanpassingen bevat.
De documenten zijn hier te vinden:
Extensions Gepubliceerde versie
Extensions Werkversie
Dit onderdeel is niet normatief.
Doel van dit hoofdstuk: Hoe kan je je applicatie landschap inrichten zodat je APIs kan aanbieden. Welke componenten zijn hiervoor nodig. Hoe ga je om met opschalen, beschikbaarheid. Wat zijn afwegingen om beveiliging al dan niet toe te passen.
In de huidige versie van de Nederlandse API strategie bevat dit hoofdstuk alleen het onderwerp OAuth. In een volgende versie komen de volgende onderwerpen erbij:
Deze sectie beschrijft de uitgangspunten voor het Nederlands profiel OAuth. het profiel zelf is een op zichzelfstaand document.
Het opstellen van deze standaard is voortgekomen uit het Expert advies OAuth [Expert]. Daarin wordt aangeraden eerst een nederlands profiel op stellen alvorens OAuth op de pas toe of leg uit lijst van het forum standaardisatie te plaatsen.
Als organisatorisch werkingsgebied wordt geadviseerd: Nederlandse overheden (Rijk, provincies, gemeenten en waterschappen) en instellingen uit de (semi-) publieke sector
Als functioneel toepassingsgebied wordt voorgesteld: Het gebruik van OAuth 2.0 is verplicht voor applicaties waarbij gebruikers (resource owner) toestemming geven (impliciet of expliciet) aan een dienst (van een derde) om namens hem toegang te krijgen tot specifieke gegevens via een RESTful API. Het gaat dan om een RESTful API waar de resource owner recht tot toegang heeft.
de expertgroep is op 7 juli en op 22 september 2016 bijeengekomen om de standaarden, de aandachtspunten en openstaande vragen uit het voorbereidingsdossier te bespreken. Daarbij is vastgesteld dat OpenID Connect niet voor opneming op de lijst open standaarden in aanmerking komt.
Het Nederlands profiel OAuth baseren we het internationale iGOV OAuth 2.0 profiel [iGOV.OAuth2] we nemen niet alle keuzes van dit internationale profiel over aangezien dit een aantal keuzes bevat die sterk leunen op de amerikaanse situatie. Het kan het best beschouwd worden als een fork waar we in ons profiel aangeven waar we afwijken. iGov heeft twee naast het OAuth profiel ook een OpenID connect profiel [iGOV.OpenID] wanneer mogelijk ook OpenID connect op de pas toe of leg uit lijst van het Forum standaardisatie komt kan dit Nederlandse profiel uitgebreid worden met een Nederlandse variant van het iGov OpenID Connect profiel. De usecase die hieronder wordt beschreven sorteerd daar al op voor.
Het Nederlands profiel OAuth is hier te vinden: https://geonovum.github.io/KP-APIs-OAuthNL/#dutch-government-assurance-profile-for-oauth-2-0 In aanvulling hierop is er een document dat de verschillen met iGOV kort samenvat en voorziet van rationales. https://github.com/Geonovum/KP-APIs-OAuthNL/blob/master/Additional%20specification%20and%20constraints%20of%20iGov-NL%20to%20the%20iGov%20profile.md
Dit onderdeel is niet normatief.
Dit hoofdstuk gaat in op de vraag: Hoe kan je je applicatie landschap inrichten zodat je APIs kan aanbieden. Welke componenten zijn hiervoor nodig. Hoe ga je om met opschalen, beschikbaarheid. Wat zijn afwegingen om beveiliging al dan niet toe te passen.
Doel van dit hoofdstuk is om een hoog niveau overzicht te geven van relevante onderdelen en concepten en hun samenhang in een op (REST) API gebaseerde architectuur waarbij gebruik gemaakt wordt van (REST) API's als interface voor de aangeboden (gegevens)diensten. Specifiek voor REST API's is dat deze 'Resource' gericht zijn en een uniforme manier bieden om resources te lezen, wijzigen, toevoegen of verwijderen.
Figuur 1: De plaats van API's bij aanbod en gebruik van (gegevens)diensten;
Figuur 1 toont de plaats van API's in de gegevensuitwisseling en relevante onderwerpen in deze context. Bij de Dienst afnemer speelt het gebruik van API's, bij de Dienst aanbieder speelt het aanbieden van API's.
In dit hoofdstuk wordt specifiek ingegaan op de 'aanbod kant': het onderdeel 'Diensten toegang' in het schema.
Een diensten aanbieder ontsluit zijn diensten middels API's aan een diensten afnemer; om deze API's gecontroleerd aan te bieden is management en beheer van de API's van de organisatie noodzakelijk.
Een organisatie heeft verschillende soorten API's:
Open API's: voor ontsluiten van diensten zonder toegangsbeperking bv open data.
Gesloten API's: voor ontsluiten van diensten met toegangsbeperking bv persoonsgegevens en vertrouwelijke gegevens of diensten voor specifieke partijen.
Figuur 2 beschrijft vanuit het perspectief van een overheidsorganisatie als dienstaanbieder de onderwerpen die aandacht vragen in een op API's gebaseerde architectuur. Hieronder worden deze onderwerpen uitgebreider toegelicht.
Figuur 2: Onderdelen van een API architectuur - Algemeen overzicht
Dit is het runtime onderdeel dat op de organisatiegrens van de diensten aanbieder de API-aanroepen ontvangt.
Throttling
Het beschermen van de dienst tegen overbelasting door de hoeveelheid aanvragen te beperken. Een aandachtspunt hierbij is de SLA afspraak die mogelijk hierbij van toepassing is en dat kritische bedrijfsprocessen de vereiste beschikbaarheid verkrijgen of behouden;
Authenticatie
Het vaststellen van de identiteit van de afnemer van de API;
(Zie ook : https://www.noraonline.nl/wiki/Identity_%26_Access_Management)
Autorisatie
Het bepalen of de afnemer recht heeft tot gebruik van de API;
Routering
Dit betreft het routeren van de API-aanroep naar de juiste achterliggende applicatie;
Logging
Dit betreft het loggen van API aanroepen van diensten afnemers;
Dit onderdeel betreft het beheren van de API's van de dienstenaanbieders. Op basis van de registratie van API's kan de life-cycle van de API beheerd worden, de runtime omgeving worden ingericht en partners en developers worden voorzien van informatie over het gebruik van de API's;
Toegang De dienstaanbieder administreert wie toegang heeft tot welke API. De runtime omgeving (API-gateway) wordt geconfigureerd volgens de gewenste toegangsregels om de toegang te bewaken;
API Meta Data De dienstaanbieder administreert welke API's door de onderneming aangeboden worden. Dit betreft zowel open API's als gesloten API's;
API Life Cycle De dienstaanbieder beheert de levenscyclus van de API's (design, test, productie, afvoer);
Monitoring De dienstaanbieder monitort beschikbaarheid en gebruik van de API's;
Het Developer portal ondersteunt de ontwikkelaar bij het gebruik van API's. Bijvoorbeeld door middel van documentatie, voorbeelden, API-register (overzicht van alle beschikbare API's), sandbox voor experimenten en ook 'onboarding' / aanmelden voor toegang en developer account beheer.
De applicaties van de afnemer maken gebruik van de diensten van de dienstenaanbieder door het aanroepen van API's. De applicaties van de aanbieder leveren de diensten door het aanbieden van API's.
In gevallen waar de identiteit van de dienstenaanvrager van belang is en onderdeel van de toegangs controle en gebruiksmonitoring, is de relatie met het identity management systeem van de organisatie relevant.
(Zie ook : https://www.noraonline.nl/wiki/Begrippen_IAM)
Dit onderdeel is niet normatief.
Operations of an API are guaranteed to be safe and/or idempotent if that has been specified.
The client state is tracked fully at the client.
A RESTful API is an application programming interface that supports the default HTTP operations GET, PUT, POST, PATCH and DELETE.
Define resources and the underlying entities, fields and so on (the information model ad the external interface) in Dutch. English is allowed in case there is an official English glossary.
Names of resources are nouns and always in the plural form, e.g. aanvragen , activiteiten, vergunningen, even when it applies to single resources.
Preferrably, create relation within the endpoint if a relation can only exist with another resource (nested resource). In that case, the dependent resource does not have its own endpoint.
Provide a comma-separated list of field names using the query parameter fields
te retrieve a custom representation. In case non-existent field names are
passed, a 404 Bad Request error message is returned.
"Operations that do not fit the CRUD model are implemented as follows:
Treat an operation as a sub-resource.
Only in exceptional cases, an operator is implemented as an endpoint."
Encrypt connections using at least TLS v1.3. Use TLS v1.2 as a fall-back option only. In case of access restrictions use two-way TLD. Since the connection is always encrypted, the authentication method is straightforward. This allows the application of basic authentication tokens instead of encrypted authentication tokens.
Preferrably, APIs should require at least a sign-up process that involves accepting its fair use policy before an API key is issued.
There is an inherent security issue when passing tokens as a query parameter, because most Web servers store query parameters in the server logs.
In the case of APIs that have access-restrictions or purpose-limitations, additional authentication based on PKIoverheid certificates and mutual TLS authentication should be provided.
Publish specifications (documentation) as Open API Specification (OAS) 3.0 or higher.
Publish API documentation in Dutch. You may refer to existing documentation in Engelish and in case there is an official English glossary avaialble.
API changes and a deprecation schedule should be published not only as a changelog on a publicly available blog but also through a mailing list.
Old and new versions (maximum 3) of an API should be provided concurrently for a limited, maximum 1 year transition period.
The URI of an API should include the major version number only. The minor and patch version numbers are in the response header of the message. Minor and patch versions have no impact on existing code, but major version do.
Using the Warning
response header in all responses of the deprecated APIs,
users are informed of the deprecation and upcoming removal date.
APIs receive and send JSON.
APIs may support JSON Schema (<http: json-schema.org)="">to allow and facilitate validation.
Besides JSON, APIs should support other representations as XML and RDF using the
default HTTP content negotiation mechanism. In case the requested format cannot
be provided, a 406 ot Acceptable
response is sent.
Check the Content-Type
header is application/json
or another supported
content types, otherwise send the HTTP status code 415 Unsupported Media Type
.
Define field names in a such a way that the first word starts with a lower case and subsequent words start with a capital letter, with no intervening spaces or punctiation.
The assumption is that REST clients and Web browsers (either with or without add-ons or extensions) can pretty print JSON.
By default, don't apply an envelope.
POST
, PUT
, and PATCH
payloadsAPIs support at least JSON-encoded POST
, PUT
, and PATCH
payloads. Encoded
form data (application/x-www-form-urlencoded
) is not supported.
Use uniqe query parameters that correspond to the fields that can be queried.
sorteer
to sortSpecify the comma-separated field to sort using the generic query parameter
sorteer
. Placing a minus sign (-
) in front of a field name, the field is
sorted in descending order.
zoek
for full-text searchAPIs support full-text searching using the query parameter zoek
.
*
and ?
wildcard characters for full-text search APIsFull-text search APIs should support two wildcard characters:
*
Matches zero or more (non-space) characters
?
Matches exactly one (non-space) character
Preferrably, GEO APIs should support the GeoJSON standard (RFC-7946).
In case a JSON (application/json
) response contains a geometry, represent it
in the same way as the geometry
object of GeoJSON
(RFC-7946):
{
"type": "Point",
"coordinates": [125.6, 10.1]
}
POST
endpoint for GEO queriesSpatial queries are sent in a POST
to a dedicated endpoint.
POST
endpointsMixed queries may include both spatial and property queries.
In case of a global query /api/v1/_zoek
, results should be placed in the
relevant geometric context, because results from different collections are
retrieved. Express the name of the collection to which the results belongs in
the singular form using the property type
.
General usage of the European ETRS89 coordinate reference system (CRS) is preferable, but is not necessarily the default CRS. Hence, the CRS has to be explicitly included in each request.
The coordinate reference system (CRS) for both the request and the response are
passed as part of the request headers and reponse headers. In case this header
is missing, send the HTTP status code 412 Precondition Failed
.
The CRS for the geometry in the response body is defined using the Accept-Crs
header. In case the API does not support the requested CRS, send the HTTP status
code 406 Not Acceptable
.
application/hal+json
for paginationAdd two reserved fields _links
(required) and _embedded
(optional) to the
representation. Pass pagination meta data as HTTP headers.
For caching apply the default HTTP caching mechanisms using a few additional
HTTP headers (ETag
or Last-Modified
) and functionality to determine wether
a few specific HTTP headers are supplied (If-None-Match
or
If-Modified-Since
).
To prevent server overload and the guarantee a high service level, apply rate limiting to API requests.
Use the HTTP header X-Rate-Limit
to inform users of rate limits. In case the
rate limits are exceeded, send the HTTP status code 429 Too Many Requests
.
API support the default error messages of the HTTP 400 and 500 status code ranges, including the parsable JSON representation (RFC-7807).
APIs should at least support the following HTTP status codes: 200, 201, 204, 304, 400, 401, 403, 405, 406, 409, 410, 415, 422, 429, 500, and 503.
URIs to retrieve collections of resources or individual resources don't include a trailing slash. A resource is only available at one endpoint/path. Resource paths end without a slash.
In JavaScript, only use restricted API-keys, linked to specific characteristics of the client-application (web application or mobile application), e.g. a clientId and/or referring URL.
Check the domain of the incoming request and generate the response header
depending on whether this domain may send requests or not (whitelist). In that
case, only add this particular domain to the response header
Access-Control-Allow-Origin
.
**NOTE: It is technically possible to pass a wildcard ("*") in the response
header Access-Control-Allow-Origin
to allow all sources. However, this is
malpractice!**
Publish up-to-date documentation in the Open API Specification (OAS) at the publicly accessible root endpoint of the API in JSON format:
https://service.omgevingswet.overheid.nl/publiek/catalogus/api/raadplegen/v1
Makes the OAS relevant to v1 of the API available.
Thus, the up-to-date documentation is linked to a unique location (that is always concurrent with the features available in the API).