From standaarden
Guides implementation of Digikoppeling interfaces (ebMS2, WUS, REST-API, large messages) for secure message exchange between Dutch government organizations. Includes decision tree and code examples.
npx claudepluginhub developer-overheid-nl/skills-marketplace --plugin standaardenThis skill is limited to using the following tools:
> **CONCEPT — Let op:** Deze skill is geen officieel product van Logius. De beschrijvingen zijn informatieve samenvattingen — niet de officiële standaarden zelf. De definities op [forumstandaardisatie.nl](https://www.forumstandaardisatie.nl/open-standaarden) en [Logius](https://www.logius.nl) zijn altijd leidend. Overheidsorganisaties die generatieve AI inzetten dienen te voldoen aan het [Overh...
Monitors deployed URLs for regressions after deploys, merges, or upgrades by checking HTTP status, console errors, network failures, performance (LCP/CLS/INP), content, and API health.
Share bugs, ideas, or general feedback.
CONCEPT — Let op: Deze skill is geen officieel product van Logius. De beschrijvingen zijn informatieve samenvattingen — niet de officiële standaarden zelf. De definities op forumstandaardisatie.nl en Logius zijn altijd leidend. Overheidsorganisaties die generatieve AI inzetten dienen te voldoen aan het Overheidsbreed standpunt voor de inzet van generatieve AI. Zie DISCLAIMER.md en onze verantwoording.
Agent-instructie: Deze skill helpt bij het implementeren van Digikoppeling koppelvlakken. Gebruik de beslisboom om het juiste profiel te kiezen. De implementatievoorbeelden bevatten werkende code voor alle vier koppelvlakstandaarden.
Digikoppeling is de Nederlandse standaard voor beveiligde elektronische gegevensuitwisseling tussen overheidsorganisaties. Het definieert de architectuur en koppelvlakspecificaties waarmee overheden op een gestandaardiseerde, veilige en betrouwbare manier berichten en gegevens uitwisselen. Digikoppeling is opgenomen op de "pas toe of leg uit"-lijst van het Forum Standaardisatie.
Net als andere Logius-standaarden kent Digikoppeling twee publicatiekanalen:
gitdocumentatie.logius.nllogius-standaarden.github.io| Repository | Beschrijving | Licentie | Vastgesteld | Draft |
|---|---|---|---|---|
| Digikoppeling-Architectuur | Overkoepelende architectuurbeschrijving | CC-BY-4.0 | v2.1.1 | Draft |
| Digikoppeling-Koppelvlakstandaard-REST-API | REST-API koppelvlakspecificatie | CC-BY-4.0 | v4.0.0 | Draft |
| Digikoppeling-Koppelvlakstandaard-ebMS2 | ebMS2 koppelvlakspecificatie | CC-BY-4.0 | v3.3.2 | Draft |
| Digikoppeling-Koppelvlakstandaard-WUS | WUS (WSDL/UDDI/SOAP) koppelvlakspecificatie | CC-BY-4.0 | v3.8.1 | Draft |
| Digikoppeling-Koppelvlakstandaard-GB | Grote Berichten koppelvlakspecificatie | CC-BY-4.0 | v3.8.1 | Draft |
| Digikoppeling-Beveiligingsstandaarden-en-voorschriften | Beveiligingsstandaarden en -voorschriften | CC-BY-4.0 | v3.0.0 | Draft |
| Digikoppeling-Identificatie-en-Authenticatie | Identificatie en authenticatie | CC-BY-4.0 | v1.5.0 | Draft |
| OIN-Stelsel | Organisatie Identificatie Nummer stelsel | CC-BY-4.0 | v3.0.0 | Draft |
| Digikoppeling-Beheermodel | Beheermodel voor Digikoppeling | CC-BY-4.0 | v1.8 | Draft |
| Repository | Beschrijving | Licentie | Vastgesteld | Draft |
|---|---|---|---|---|
| Digikoppeling-Gebruik-en-achtergrond-certificaten | Gebruik van PKIoverheid-certificaten | CC-BY-4.0 | v1.6.3 | Draft |
| Digikoppeling-Handreiking-Adressering-en-Routering | Handreiking voor adressering en routering | CC-BY-4.0 | v1.1.0 | Draft |
| Digikoppeling-Best-Practices-ebMS2 | Best practices voor ebMS2 implementatie | CC-BY-4.0 | v3.2.2 | Draft |
| Digikoppeling-Best-Practices-WUS | Best practices voor WUS implementatie | CC-BY-4.0 | v1.10.2 | Draft |
| Digikoppeling-Best-Practices-GB | Best practices voor Grote Berichten | CC-BY-4.0 | v3.2.0 | Draft |
| Digikoppeling-Overzicht-Actuele-Documentatie-en-Compliance | Overzicht documentatie en compliance | CC-BY-4.0 | v1.13.0 | Draft |
| Digikoppeling-Wat-is-Digikoppeling | Introductie en uitleg | CC-BY-4.0 | v1.1.2 | Draft |
| Digikoppeling-Algemeen | Digikoppeling Roadmap | CC-BY-4.0 | v2026-2027 | Draft |
De keuze voor het juiste Digikoppeling-profiel hangt af van de functionele en niet-functionele eisen van de berichtuitwisseling. Gebruik de volgende beslisboom:
Berichtgrootte > 20 MiB?
JA --> Grote Berichten (aanvullend op REST-API, WUS of ebMS2)
NEE --> Ga verder
Is snelheid/eenvoud belangrijk en past een synchrone request/response?
JA --> Is een REST-API beschikbaar/gewenst?
JA --> REST-API profiel (FSC verplicht, zie /ls-fsc)
NEE --> WUS profiel (2W-be)
NEE --> Ga verder
Is betrouwbare (reliable) aflevering vereist?
JA --> ebMS2 reliable profiel (osb-rm)
NEE --> ebMS2 best-effort profiel (osb-be)
Gaat het bericht via een niet-vertrouwde intermediair?
JA --> Kies de signed (-S) of signed+encrypted (-SE/-E) variant van het gekozen profiel
NEE --> Basisprofiel volstaat
| Profiel | Synchroon | Asynchroon | Best-effort | Reliable | Signed | Encrypted |
|---|---|---|---|---|---|---|
| REST-API | Ja | Nee | Ja | Nee | Nee* | Nee* |
| 2W-be | Ja | Nee | Ja | Nee | Nee | Nee |
| 2W-be-S | Ja | Nee | Ja | Nee | Ja | Nee |
| 2W-be-SE | Ja | Nee | Ja | Nee | Ja | Ja |
| osb-be | Nee | Ja | Ja | Nee | Nee | Nee |
| osb-rm | Nee | Ja | Nee | Ja | Nee | Nee |
| osb-be-S | Nee | Ja | Ja | Nee | Ja | Nee |
| osb-rm-S | Nee | Ja | Nee | Ja | Ja | Nee |
| osb-be-E | Nee | Ja | Ja | Nee | Nee | Ja |
| osb-rm-E | Nee | Ja | Nee | Ja | Nee | Ja |
| Grote Berichten | n.v.t. | n.v.t. | Ja | Nee | Nee | Nee** |
* REST-API maakt gebruik van TLS voor transportbeveiliging. Signing en encryptie op berichtniveau zijn niet gestandaardiseerd binnen het REST-API-profiel, maar kunnen op applicatieniveau worden toegepast (bijv. via JWS/JWE).
** Grote Berichten gebruikt TLS voor transport. Payload-encryptie kan aanvullend worden toegepast maar is niet voorgeschreven in het profiel.
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
app = FastAPI(
title="Digikoppeling REST-API Voorbeeld",
version="1.0.0",
contact={"name": "API Support", "email": "support@example.com"},
servers=[{"url": "https://api.example.com/dk/v1"}]
)
@app.middleware("http")
async def add_digikoppeling_headers(request: Request, call_next):
"""Voeg verplichte Digikoppeling headers toe aan responses."""
response = await call_next(request)
response.headers["API-Version"] = "1.0.0"
response.headers["Strict-Transport-Security"] = "max-age=31536000"
response.headers["X-Content-Type-Options"] = "nosniff"
response.headers["X-Frame-Options"] = "DENY"
response.headers["Content-Security-Policy"] = "frame-ancestors 'none'"
response.headers["Cache-Control"] = "no-store"
return response
@app.get("/v1/resources/{resource_id}")
async def get_resource(resource_id: str, request: Request):
"""Beveiligd endpoint - mTLS met PKIoverheid certificaat vereist."""
# OIN uit het client certificaat (via reverse proxy/API gateway)
client_oin = request.headers.get("X-Client-OIN")
if not client_oin:
raise HTTPException(status_code=403, detail="OIN niet gevonden in certificaat")
return {"id": resource_id, "requested_by_oin": client_oin}
@app.exception_handler(HTTPException)
async def problem_json_handler(request: Request, exc: HTTPException):
"""RFC 9457 problem+json foutafhandeling (verplicht per API Design Rules)."""
return JSONResponse(
status_code=exc.status_code,
content={
"type": f"https://api.example.com/errors/{exc.status_code}",
"title": exc.detail,
"status": exc.status_code,
"instance": str(request.url),
},
media_type="application/problem+json"
)
from zeep import Client
from zeep.transports import Transport
from requests import Session
# mTLS sessie met PKIoverheid certificaten
session = Session()
session.cert = ("pkio_client_cert.pem", "pkio_client_key.pem")
session.verify = "pkio_ca_bundle.pem" # PKIoverheid CA chain
transport = Transport(session=session)
# WSDL-gebaseerde client (service contract)
client = Client(
"https://service.example.com/dk/wus?wsdl",
transport=transport
)
# Synchrone bevraging (profiel 2W-be)
response = client.service.GeefPersoon(
BSN="999990342",
Organisatie={"OIN": "00000001823288444000"}
)
print(f"Naam: {response.Naam}")
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:wsa="http://www.w3.org/2005/08/addressing"
xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd">
<soapenv:Header>
<!-- WS-Addressing (verplicht voor routing) -->
<wsa:MessageID>550e8400-e29b-41d4-a716-446655440000@urn:osb:dgd</wsa:MessageID>
<wsa:To>https://service.example.com/dk/wus</wsa:To>
<wsa:Action>http://example.com/GeefPersoon</wsa:Action>
<!-- WS-Security (profiel 2W-be-S: signed) -->
<wsse:Security>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<!-- SHA-256 digest, PKIoverheid certificaat -->
</ds:Signature>
</wsse:Security>
</soapenv:Header>
<soapenv:Body>
<GeefPersoonRequest>
<BSN>999990342</BSN>
</GeefPersoonRequest>
</soapenv:Body>
</soapenv:Envelope>
<?xml version="1.0" encoding="UTF-8"?>
<soapenv:Envelope
xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:eb="http://www.oasis-open.org/committees/ebxml-msg/schema/msg-header-2_0.xsd"
xmlns:xlink="http://www.w3.org/1999/xlink">
<soapenv:Header>
<eb:MessageHeader soapenv:mustUnderstand="1" eb:version="2.0">
<eb:From>
<eb:PartyId eb:type="urn:osb:oin">00000001823288444000</eb:PartyId>
</eb:From>
<eb:To>
<eb:PartyId eb:type="urn:osb:oin">00000001234567890000</eb:PartyId>
</eb:To>
<eb:CPAId>cpa_oin1_oin2_service</eb:CPAId>
<eb:ConversationId>conv-2024-001</eb:ConversationId>
<eb:Service>urn:example:melding</eb:Service>
<eb:Action>Indienen</eb:Action>
<eb:MessageData>
<eb:MessageId>msg-550e8400@urn:osb:dgd</eb:MessageId>
<eb:Timestamp>2024-01-15T10:30:00Z</eb:Timestamp>
</eb:MessageData>
</eb:MessageHeader>
<!-- Profiel osb-rm: Reliable Messaging -->
<eb:AckRequested soapenv:mustUnderstand="1" eb:version="2.0"
eb:signed="false" soapenv:actor="urn:oasis:names:tc:ebxml-msg:actor:toPartyMSH"/>
</soapenv:Header>
<soapenv:Body>
<eb:Manifest eb:version="2.0">
<eb:Reference xlink:href="cid:payload@example.com" xlink:role="payload"/>
</eb:Manifest>
</soapenv:Body>
</soapenv:Envelope>
# Stap 1: Metadata verzenden via Digikoppeling (REST/WUS/ebMS2)
# Het metadatabericht bevat de download-URL, bestandsgrootte en checksum
# Stap 2: Ontvanger downloadt bestand via HTTPS GET met BYTE-RANGE
# Eerste request: geheel bestand
curl -X GET https://sender.example.com/gb/files/document-123 \
--cert pkio_client_cert.pem --key pkio_client_key.pem \
--cacert pkio_ca_bundle.pem \
-H "Accept: application/octet-stream" \
-o document.pdf
# Bij onderbreking: hervatten met Range header
curl -X GET https://sender.example.com/gb/files/document-123 \
--cert pkio_client_cert.pem --key pkio_client_key.pem \
--cacert pkio_ca_bundle.pem \
-H "Range: bytes=1048576-" \
-H "If-Match: \"etag-value-from-previous-response\"" \
-C - -o document.pdf
# Response: 206 Partial Content met Content-Range header
# Verzender uploadt bestand naar ontvanger
curl -X PUT https://receiver.example.com/gb/upload/document-123 \
--cert pkio_client_cert.pem --key pkio_client_key.pem \
--cacert pkio_ca_bundle.pem \
-H "Content-Type: application/octet-stream" \
-H "Content-Length: 52428800" \
--data-binary @large_document.pdf
# Response: 200 OK of 201 Created (spec schrijft geen specifieke response code voor)
server {
listen 443 ssl;
server_name api.example.com;
# PKIoverheid server certificaat
ssl_certificate /etc/ssl/pkio/server_cert.pem;
ssl_certificate_key /etc/ssl/pkio/server_key.pem;
# mTLS: PKIoverheid client certificaat vereist
ssl_client_certificate /etc/ssl/pkio/pkio_ca_chain.pem;
ssl_verify_client on;
ssl_verify_depth 4;
# TLS configuratie (NCSC 2025 richtlijnen)
ssl_protocols TLSv1.2 TLSv1.3; # TLS001/TLS004
ssl_prefer_server_ciphers on;
ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384';
# Client certificaat Subject DN doorgeven aan applicatie
# $ssl_client_s_dn bevat de volledige DN, bijv. "serialNumber=00000001823288444000,CN=Mijn Org"
proxy_set_header X-Client-DN $ssl_client_s_dn;
location /dk/v1/ {
proxy_pass http://localhost:8080;
}
}
| Status | REST-API | WUS | ebMS2 |
|---|---|---|---|
| 200 | OK - resource opgehaald | N/A (SOAP 200) | N/A |
| 206 | Partial Content (Grote Berichten) | N/A | N/A |
| 400 | Ongeldig verzoek | SOAP Fault | eb:Error |
| 401 | Niet geauthenticeerd | SOAP Fault | eb:Error |
| 403 | OIN niet geautoriseerd | SOAP Fault | eb:Error |
| 404 | Resource niet gevonden | SOAP Fault | N/A |
| 405 | Methode niet toegestaan | N/A | N/A |
| 500 | Interne fout | SOAP Fault | eb:Error |
| 503 | Service niet beschikbaar | SOAP Fault | eb:Error |
{
"type": "https://api.example.com/errors/oin-unauthorized",
"title": "OIN niet geautoriseerd",
"status": 403,
"detail": "OIN 00000001823288444000 heeft geen toegang tot deze service",
"instance": "/dk/v1/resources/123"
}
<eb:ErrorList>
<eb:Error eb:errorCode="SecurityFailure" eb:severity="Error">
<eb:Description>OIN verificatie mislukt</eb:Description>
</eb:Error>
</eb:ErrorList>
Bij het profiel osb-rm gelden de volgende retry-regels:
Zie reference.md voor de architectuur, beveiligingsstandaarden, en gedetailleerde protocol-beschrijvingen. Zie conflicts.md voor bekende discrepanties tussen GitHub-tags en gepubliceerde versies.