API
Lees uw paspoorten en uw ketenregister uit, voeg leveranciers toe en laat u door ons waarschuwen zodra er iets verandert. De API hoort bij Plus. De sleutel maakt u aan in Mijn Ketenpas onder API; hij wordt één keer getoond.
Sleutel aanmaken in Mijn KetenpasAanmelden
Elk verzoek draagt de sleutel als bearer-token. Antwoorden zijn json, ook bij een fout.
curl https://ketenpas.nl/api/v1/paspoorten \
-H "Authorization: Bearer kp_uw_sleutel"Limieten
120 verzoeken per minuut per organisatie, over alle routes samen. Uitnodigingen tellen daarnaast apart: 25 per uur, dezelfde emmer als het scherm gebruikt.
Entiteiten
Een sleutel hoort bij één organisatie. Werkt u met entiteiten, dan maakt u per entiteit een eigen sleutel aan; de API van de moeder toont geen gegevens van een dochter.
Routes
GET /api/v1/paspoorten
Alle paspoorten van uw organisatie, met score, geldigheid en de deelbare link.
POST /api/v1/paspoorten/{id}/intrekken
Trekt een paspoort in. De gedeelde link stopt meteen met werken, ook bij wie hem al had.
GET /api/v1/keten
Uw ketenregister: elke leverancier met status, score en geldigheid.
POST /api/v1/keten
Voegt een leverancier toe. Met "uitnodigen": true gaat de uitnodiging meteen de deur uit.
POST /api/v1/keten/{id}/uitnodiging
Stuurt de uitnodiging (opnieuw) naar een leverancier die al in het register staat.
DELETE /api/v1/keten/{id}
Haalt een leverancier uit het register. De uitnodigingslink loopt daarna dood.
Een paspoort
| Veld | Type | Betekent |
|---|---|---|
| id | uuid | Het id dat u bij intrekken meegeeft. |
| label | string | null | De eigen naam die u het paspoort gaf. |
| status | "geldig" | "verlopen" | "ingetrokken" | Alleen bij geldig is de link bruikbaar. |
| score | number | 0 tot 100, op de volledige vragenlijst. |
| niveau | string | De tekstuele uitslag die bij de score hoort. |
| beoordeeldOp | string | ISO 8601, de datum van de scan erachter. |
| geldigTot | string | ISO 8601. |
| ingetrokkenOp | string | null | ISO 8601, leeg zolang het paspoort loopt. |
| url | string | null | De deelbare link; leeg zodra het paspoort niet meer geldig is. |
Een leverancier
| Veld | Type | Betekent |
|---|---|---|
| id | uuid | Het id voor de routes hieronder. |
| naam | string | |
| string | Waar de uitnodiging heen gaat. | |
| contactpersoon | string | null | |
| status | "uitgenodigd" | "gekoppeld" | "vervallen" | Uitgenodigd is ook de stand van wie nog niets ontving. |
| score | number | null | Gevuld zodra er een geldig paspoort aan hangt. |
| niveau | string | null | |
| beoordeeldOp | string | null | ISO 8601. |
| geldigTot | string | null | ISO 8601. |
| notitie | string | null | Uw eigen aantekening bij deze leverancier. |
Een leverancier toevoegen
naam en email zijn verplicht, contactpersoon en notitie mogen. Staat het adres al in uw register, dan komt er geen tweede rij bij maar een 409 met het id van de bestaande; een nachtelijke synchronisatie bouwt zo geen dubbelen op.
curl -X POST https://ketenpas.nl/api/v1/keten \
-H "Authorization: Bearer kp_uw_sleutel" \
-H "Content-Type: application/json" \
-d '{"naam":"Van Dijk Techniek","email":"security@vandijk.nl","uitnodigen":true}'Fouten
Elke fout is json met één veld: fout, met een zin erin die u kunt loggen. De statuscode is waar u op stuurt.
| Code | Betekent |
|---|---|
| 400 | De body is geen json, of een verplicht veld ontbreekt. |
| 401 | Geen of onbekende sleutel. |
| 403 | De sleutel is geldig maar het plan niet, of uw ketenlimiet is bereikt. |
| 404 | Het id bestaat niet, of hoort bij een andere organisatie. |
| 409 | De actie kan niet meer: al ingetrokken, of het adres staat al in uw register. |
| 429 | Te veel verzoeken. Zie de limieten hierboven. |
| 502 | Wij konden de uitnodiging niet versturen. De leverancier staat er wel. |
Webhooks
In plaats van elke minuut het register op te halen, kunt u één https-adres opgeven waar wij aanbellen. Dat stelt u in onder API in Mijn Ketenpas; daar staat ook het geheim en de uitkomst van de laatste poging.
| Gebeurtenis | Wanneer |
|---|---|
| leverancier.gekoppeld | Een leverancier heeft zijn paspoort met u gedeeld. |
| leverancier.vervallen | Het gekoppelde paspoort van een leverancier is verlopen of ingetrokken. Wordt één keer gestuurd, in de nachtelijke ronde. |
| test | Het testbericht vanaf de knop in Mijn Ketenpas. |
POST https://uw-systeem.nl/ketenpas
X-Ketenpas-Gebeurtenis: leverancier.gekoppeld
X-Ketenpas-Handtekening: t=1785926400,v1=9f2c...
{
"gebeurtenis": "leverancier.gekoppeld",
"verstuurdOp": "2026-08-05T09:20:00.000Z",
"gegevens": {
"leverancier": {
"id": "8f1d...",
"naam": "Van Dijk Techniek",
"email": "security@vandijk.nl"
}
}
}De handtekening controleren
Elk bericht draagt de header X-Ketenpas-Handtekening met een tijdstempel en een hmac-sha256 over tijdstempel, punt, en de letterlijke body. Reken hem na met uw geheim en vergelijk in constante tijd. Wijs een bericht af waarvan de tijdstempel meer dan vijf minuten oud is.
const [t, v1] = kop.split(",").map((deel) => deel.split("=")[1]);
const verwacht = crypto
.createHmac("sha256", geheim)
.update(`${t}.${ruweBody}`)
.digest("hex");
const klopt =
verwacht.length === v1.length &&
crypto.timingSafeEqual(Buffer.from(verwacht), Buffer.from(v1)) &&
Math.abs(Date.now() / 1000 - Number(t)) < 300;Wat wij beloven en wat niet
Wij proberen drie keer: meteen, na twee seconden en na acht seconden, met vijf seconden geduld per poging. Antwoordt u met 2xx, dan zijn we klaar; met 4xx stoppen we meteen, want dat wordt over acht seconden niet beter. Ligt uw kant er langer uit, dan is dat bericht weg: wij bewaren geen wachtrij. Gebruik GET /api/v1/keten als bodem onder uw administratie en de webhook om het sneller te weten.
Versies
Het pad draagt de versie. Binnen v1 komen er alleen velden bij, nooit weg; een veld dat verdwijnt of van betekenis verandert, wordt v2. Schrijf uw kant dus zo dat onbekende velden geen probleem zijn.