HTTP API voor de tools op developer.overheid.nl.
Deze repository bevat de API-laag voor versie 1 van de Tools API: routing, OpenAPI-validatie,
response headers, foutafhandeling en de koppeling naar de daadwerkelijke businesslogica. Die
businesslogica staat in @developer-overheid-nl/don-tools en wordt los beheerd in
don-tools.
- NestJS met Fastify als HTTP runtime
- OpenAPI request- en responsevalidatie via
openapi-backend - Gegenereerde controller- en modelbestanden op basis van
api/openapi.yaml - Implementatie-adapter in
implementation/index.ts - Events-agenda in PostgreSQL met een Pleio-harvester; de logica staat in
@developer-overheid-nl/don-tools, de adapter en levenscyclus (pool, schema, harvest-cron) inimplementation/events/ - Gestructureerde Pino-logging met veilige request-id's en één completion-log per request
- Docker image voor deployment op poort
1338
De gebundelde OpenAPI-specificatie staat in api/openapi.yaml.
Bij runtime wordt deze ook beschikbaar gemaakt op:
GET /openapi.json
Belangrijkste tools-endpoints:
POST /v1/oas/validatePOST /v1/oas/convertPOST /v1/oas/bundlePOST /v1/oas/generatePOST /v1/oas/postmanPOST /v1/arazzo/markdownPOST /v1/arazzo/mermaidPOST /v1/auth/clientsGET|POST /v1/eventsenGET|PUT|DELETE /v1/events/{id}
De events-endpoints vervangen de statische static/agenda/events.json van don-site.
Events komen uit twee bronnen:
manual: aangemaakt en beheerd viaPOST,PUTenDELETE;pleio: geharvest uit Pleio-sites. Een harvest haalt alle aankomende events op via de GraphQL-queryactivities(introspection staat bij Pleio uit, dus de query is vast) en doet een upsert op(bron, Pleio-guid). Alleen events waarvantimeUpdatedveranderd is worden bijgewerkt. Toekomstige events die de bron niet meer toont, worden verwijderd; afgelopen events blijven bewaard. Een Pleio-event dat niet te verwerken is (bijvoorbeeld zonder titel of met een url die geen http(s) is), wordt overgeslagen en met eenWARNgelogd. Zo'n event blijft in de agenda staan zoals het was. Heeft het ook geen guid, dan wordt er die run voor die bron niets verwijderd. Tekst langer dan de limieten in de OAS wordt ingekort.
Geharveste events zijn alleen bij de bron te wijzigen (PUT geeft 409). Een DELETE
verbergt zo'n event, zodat een volgende harvest het niet terugzet.
De harvest draait in het proces: bij het opstarten en daarna volgens PLEIO_HARVEST_CRON.
Een PostgreSQL advisory lock zorgt dat bij meerdere replicas maar één instantie tegelijk
harvest. De lock geldt per schema, dus omgevingen met elk een eigen DB_SCHEMA in dezelfde
database zitten elkaar niet in de weg. Bij het afsluiten wacht de app tot een lopende
harvest klaar is.
De app voert geen DDL uit. De tabel events wordt per omgeving met de hand aangemaakt in het
schema van DB_SCHEMA; de SQL daarvoor wordt buiten deze repository beheerd. De
applicatiegebruiker heeft alleen SELECT, INSERT, UPDATE en DELETE op events nodig.
Bestaat de tabel nog niet, dan geven de events-endpoints 503 en logt de harvest een fout.
Tijden volgen ADR 2.2: RFC 3339 met UTC-offset (2026-10-06T15:30:00+02:00). Velden heten
startsAt/endsAt, omdat de ADR-regel voor namen met Date format: date afdwingt.
Vereisten:
- Node.js 22.12+
- npm
Installeren en starten:
npm install
cp .env.example .env
docker compose up -d
npm run devDe API luistert standaard op http://localhost:1338. docker compose up -d start PostgreSQL
op poort 5433; .env.example wijst daar al naar. Maak daarin eenmalig de tabel events aan
(zie Database). Daarna harvest de app bij het opstarten meteen de Pleio-bronnen,
dus GET /v1/events geeft direct events. Zonder database laat je DB_HOSTNAME leeg; de events-endpoints geven dan 503.
Handige scripts:
npm run build # TypeScript build naar dist/
npm start # start de gebouwde app
npm test # Vitest tests
npm run lint # Biome lint
npm run typecheck # TypeScript typecheck zonder output
npm run generate # opnieuw genereren vanuit de live OASPORT: poort waarop de API luistert, standaard1338HOST: host waarop Fastify bindt, standaard0.0.0.0LOG_LEVEL: minimale loglevel (debug,info,warnoferror), standaardinfoOAS_FETCH_TIMEOUT_MS: timeout voor externe specificaties, standaard45000OPENAPI_MOCK: zet mock responses aan mettrue,1,yesofonOPENAPI_VALIDATE_RESPONSES: valideert succesvolle responses tegen de OAS wanneer deze optruestaatDB_HOSTNAME,DB_PORT(standaard5432),DB_USERNAME,DB_PASSWORD,DB_DBNAME,DB_SCHEMA(standaardpublic): PostgreSQL voor de events. ZonderDB_HOSTNAMEgeven de events-endpoints503en draait er geen harvest; de tools-endpoints werken gewoon. Een ongeldige waarde in een van de events-variabelen hieronder laat de app bij het opstarten stoppen met een foutmelding, in plaats van stil een standaardwaarde te gebruiken.DB_POOL_MAX: maximaal aantal databaseverbindingen, standaard5PUBLIC_BASE_URL: publiek adres vóór de gateway (bijvoorbeeldhttps://api.developer.overheid.nl/tools), gebruikt inLocationenLink. Zonder deze variabele komen die uit de request-host, en logt de app bij het opstarten een waarschuwing.EVENTS_TIME_ZONE: tijdzone voor de offset in responses, standaardEurope/AmsterdamPLEIO_SOURCES: kommagescheiden Pleio-sites, standaardhttps://digilab.pleio.nlPLEIO_HARVEST_ENABLED: zet de harvest aan of uit, standaardtruePLEIO_HARVEST_CRON: cron-schema inEVENTS_TIME_ZONE, standaard0 6 * * *PLEIO_TIMEOUT_MS: timeout per Pleio-request, standaard30000
Iedere logregel is één JSON-object op stdout met time, level, msg,
app, component en operation. app is altijd tools-api. HTTP-logs
gebruiken daarnaast request_id, method, route, path, status_code,
duration_ms en response_bytes. Querystrings worden niet in path
opgenomen; alleen een 5xx response wordt als ERROR gelogd.
Mock mode kan ook direct via:
npm run dev-mockDe publieke gateway controleert vóór deze app een X-Api-Key óf een OAuth2
client-credentials-token. De runtime zelf verwacht daarom alleen verkeer van die vertrouwde
gateway. Bij lokaal gebruik vindt geen inkomende authenticatie plaats. De AUTH_CLIENT_ID en
AUTH_CLIENT_SECRET uit .env zijn uitsluitend bestemd voor de uitgaande Keycloak-adminaanroep
van POST /v1/auth/clients.
npm run generate haalt de OAS op van
https://api.developer.overheid.nl/tools/v1/openapi.json. Met
OPENAPI_SOURCE=api/openapi.yaml npm run generate genereert het vanuit een lokaal bestand,
bijvoorbeeld om nieuwe operaties toe te voegen die nog niet gepubliceerd zijn. CI gebruikt dit
om te controleren dat de gegenereerde code bij de gecommitte OAS past. Het script:
- valt terug op de gecommitte
api/openapi.yamlals de gepubliceerde OAS niet op te halen is; - controleert en verwijdert vier identieke legacy-componentvelden op rootniveau;
- corrigeert de API-key en client-credentials-eis naar twee alternatieve security-requirements;
- bundelt de OAS met een vastgezette Redocly-versie;
- valideert de bundel met DON ADR 2.1;
- genereert NestJS/Fastify met een vastgezette templatecommit en OpenAPI Generator-versie;
- vervangt alleen de gegenereerde mappen en laat
implementation/ongemoeid.
De projectspecifieke code na generatie staat in implementation/: de adapter in
implementation/index.ts roept de acht functies uit @developer-overheid-nl/don-tools aan,
en implementation/events/ is de adapter voor de events-agenda uit hetzelfde package: HTTP
(paginering, Location), config uit de omgeving, de databasepool en de harvest-cron.
Voor generatie zijn Node.js 22.12+, npm, Git en een Java-runtime nodig.
don-tools-api is alleen de HTTP-adapter. De herbruikbare logica zit in de
apart gepubliceerde package:
npm install @developer-overheid-nl/don-tools@0.0.3Build lokaal:
docker build -t don-tools-api .Run lokaal:
docker run --rm -p 1338:1338 don-tools-apiDraai minimaal:
npm run lint
npm run typecheck
npm run build
npm testBij wijzigingen aan de OAS of de template: draai ook npm run generate en controleer
dat alleen de verwachte gegenereerde bestanden veranderen.
api/ OpenAPI contract en gegenereerde API interfaces
app/ NestJS/Fastify bootstrap en OpenAPI middleware
controllers/ Gegenereerde NestJS controllers
decorators/ Gegenereerde request decorators
implementation/ Handgeschreven adapter naar don-tools en de events-implementatie
models/ Gegenereerde request/response modellen
scripts/ Reproduceerbare OAS-normalisatie en codegeneratie
test/ Vitest tests