WTTA-Dossier API
Met de publieke REST API koppel je je eigen systemen (zoals planning-, HR- of backofficesoftware) aan WTTA-Dossier. De API biedt volledige CRUD op arbeidskrachten, documenten, inleners, plaatsingen en taken, geschikt voor uitzendbureaus, detacheerders en payrollers die hun Wtta-compliance willen automatiseren.
Alle endpoints staan onder de volgende basis-URL en accepteren en retourneren JSON (behalve de documentupload, die multipart/form-data gebruikt):
https://wtta-dossier.nl/api/v1
Datums gebruiken het formaat YYYY-MM-DD, tijdstippen zijn ISO 8601 in UTC. Id's zijn ULID-strings. Responsvelden gebruiken snake_case (first_name), verzoekvelden camelCase (firstName).
De API is beschikbaar in de pakketten Groei en Pro; tijdens de gratis proefperiode kan elk pakket de API uitproberen. Zonder passend pakket geeft elke aanroep een 403 (of 402 bij een verlopen proefperiode).
Authenticatie
Elk verzoek vereist een API-sleutel in de Authorization-header. Sleutels beginnen met nd_live_, gelden voor je hele organisatie en maak je aan op de API-pagina in het dashboard (alleen de eigenaar).
curl "https://wtta-dossier.nl/api/v1/workers" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Gebruik de API uitsluitend server-to-server: roep de API nooit rechtstreeks vanuit een browser aan, want daarmee lekt je sleutel naar bezoekers.
Foutafhandeling
Fouten hebben altijd dezelfde envelope, met een machine-leesbare code en een leesbare message.
| Status | Code | Betekenis |
| 400 | validation_error | De aanvraag is ongeldig; de message beschrijft per veld wat er mist. |
| 401 | unauthorized | Geen, ongeldige of ingetrokken API-sleutel. |
| 402 | payment_required | Schrijfacties vereisen een actief abonnement of lopende proefperiode. |
| 403 | forbidden | De actie is niet toegestaan. |
| 404 | not_found | De resource bestaat niet of hoort bij een andere organisatie. |
| 409 | conflict | De aanvraag botst met de huidige staat van de resource. |
| 413 | payload_too_large | Het geüploade bestand is te groot. |
| 429 | rate_limited | Te veel aanvragen; zie de X-RateLimit-headers. |
| 500 | internal_error | Onverwachte fout aan onze kant. |
Rate limits
Per API-sleutel zijn maximaal 120 verzoeken per minuut toegestaan (schuivend venster). Elke respons bevat de headers X-RateLimit-Limit, X-RateLimit-Remaining en X-RateLimit-Reset. Bij overschrijding krijg je een 429 rate_limited.
Paginering
Alle lijst-endpoints ondersteunen limit (standaard 25, maximaal 200) en offset. De respons bevat naast de resultaten altijd een total met het totale aantal, zodat je kunt doorbladeren.
Logging en retentie
Elke API-aanroep wordt gelogd: methode, pad, statuscode, duur en de gebruikte sleutel, plus de request- en response-body ingekort tot 2.048 tekens. Logregels zijn 90 dagen zichtbaar in het dashboard, inclusief een grafiek van het gebruik per dag. Handelingen via de API verschijnen daarnaast in de audit trail onder de naam van de sleutel.
Workers (arbeidskrachten)
Arbeidskrachten vormen de kern van het dossier. Bij het aanmaken worden automatisch de bijbehorende dossiertaken gegenereerd (zoals de ID-check). Verwijderen is een archivering: het dossier blijft bewaard voor de wettelijke bewijslast.
GET /api/v1/workers
Arbeidskrachten ophalen
Geeft een gepagineerde lijst, inclusief de dossiervolledigheid (completeness, 0 tot 100) per arbeidskracht.
Queryparameters
| Veld | Type | Omschrijving |
search | string | Zoekt in voornaam, achternaam en e-mailadres. |
nationality | string | Filter: nl, eu of derde_land. |
housing | string | Filter op huisvesting via het bureau: ja of nee. |
contract | string | Filter op contracttype. |
limit | number | Aantal resultaten per pagina (standaard 25, maximaal 200). |
offset | number | Aantal resultaten dat wordt overgeslagen (standaard 0). |
Voorbeeld
curl "https://wtta-dossier.nl/api/v1/workers?nationality=eu&limit=25" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{
"workers": [
{
"id": "01JZX…",
"first_name": "Jan",
"last_name": "Kowalski",
"nationality_category": "eu",
"employment_start": "2026-03-01",
"employment_end": null,
"contract_type": "uitzendovereenkomst",
"housing_provided": true,
"email": "jan@example.com",
"completeness": 80,
"created_at": "2026-03-01T09:12:00.000Z"
}
],
"total": 1
}
GET /api/v1/workers/{id}
Arbeidskracht ophalen
Geeft het volledige dossier: de arbeidskracht, de dossierchecklist, gekoppelde documenten en plaatsingen.
Voorbeeld
curl "https://wtta-dossier.nl/api/v1/workers/01JZX…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{
"worker": { "id": "01JZX…", "first_name": "Jan", … },
"checklist": {
"completeness": 80,
"items": [ { "type": "id_bewijs", "present": true, … } ]
},
"documents": [ … ],
"placements": [ … ]
}
POST /api/v1/workers
Arbeidskracht aanmaken
Maakt een arbeidskracht aan en genereert automatisch de bijbehorende dossiertaken.
Body
| Veld | Type | Omschrijving |
firstName verplicht | string | Voornaam. |
lastName verplicht | string | Achternaam. |
nationalityCategory verplicht | string | nl, eu of derde_land. |
employmentStart | string | null | Startdatum dienstverband (YYYY-MM-DD). |
employmentEnd | string | null | Einddatum dienstverband (YYYY-MM-DD). |
contractType | string | null | Contracttype, vrij tekstveld. |
housingProvided | boolean | Huisvesting via het bureau (standaard false). |
email | string | null | E-mailadres. |
notes | string | null | Vrije notities. |
Voorbeeld
curl -X POST "https://wtta-dossier.nl/api/v1/workers" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"firstName": "Jan",
"lastName": "Kowalski",
"nationalityCategory": "eu",
"employmentStart": "2026-03-01",
"housingProvided": true
}'
Respons
201 Created
{ "worker": { "id": "01JZX…", "first_name": "Jan", … } }
PATCH /api/v1/workers/{id}
Arbeidskracht bijwerken
Werkt alleen de meegestuurde velden bij. Alle velden van het aanmaak-verzoek zijn toegestaan.
Voorbeeld
curl -X PATCH "https://wtta-dossier.nl/api/v1/workers/01JZX…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "contractType": "detachering" }'
Respons
{ "worker": { "id": "01JZX…", "contract_type": "detachering", … } }
DELETE /api/v1/workers/{id}
Arbeidskracht archiveren
Soft delete: het dossier blijft bewaard maar verdwijnt uit alle lijsten.
Voorbeeld
curl -X DELETE "https://wtta-dossier.nl/api/v1/workers/01JZX…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{ "ok": true }
Documents (documentenkluis)
Documenten worden versleuteld opgeslagen in de documentenkluis. Een upload die aan een arbeidskracht is gekoppeld, rondt automatisch de bijbehorende open dossiertaken af (bijvoorbeeld de ID-check na het uploaden van een id_bewijs).
GET /api/v1/documents
Documenten ophalen
Queryparameters
| Veld | Type | Omschrijving |
type | string | Filter op documenttype. Mogelijke waarden: vog_rp, sna_certificaat, snf_certificaat, id_bewijs, werkvergunning, arbeidsovereenkomst, loonstrook, belastingverklaring, inspectierapport, betaalbewijs, ketenverklaring, overig. |
workerId | string | Alleen documenten van deze arbeidskracht. |
search | string | Zoekt in titel en bestandsnaam. |
limit | number | Aantal resultaten per pagina (standaard 25, maximaal 200). |
offset | number | Aantal resultaten dat wordt overgeslagen (standaard 0). |
Voorbeeld
curl "https://wtta-dossier.nl/api/v1/documents?type=id_bewijs" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{
"documents": [
{
"id": "01JZY…",
"type": "id_bewijs",
"title": "Paspoort Jan Kowalski",
"file_name": "paspoort.pdf",
"mime_type": "application/pdf",
"size_bytes": 182044,
"expiry_date": "2030-05-01",
"worker_id": "01JZX…",
"worker_name": "Jan Kowalski",
"created_at": "2026-03-02T10:00:00.000Z"
}
],
"total": 1
}
GET /api/v1/documents/{id}
Document ophalen
Voorbeeld
curl "https://wtta-dossier.nl/api/v1/documents/01JZY…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{ "document": { "id": "01JZY…", "type": "id_bewijs", … } }
POST /api/v1/documents
Document uploaden
Upload als multipart/form-data met een verplicht file-veld. De respons bevat completedTasks: taken die door deze upload automatisch zijn afgerond.
Body
| Veld | Type | Omschrijving |
file verplicht | bestand | Het bestand zelf (multipart-veld). |
type | string | Documenttype (standaard overig). Mogelijke waarden: vog_rp, sna_certificaat, snf_certificaat, id_bewijs, werkvergunning, arbeidsovereenkomst, loonstrook, belastingverklaring, inspectierapport, betaalbewijs, ketenverklaring, overig. |
title | string | Titel (standaard de bestandsnaam). |
expiryDate | string | Vervaldatum (YYYY-MM-DD). |
workerId | string | Koppel aan een arbeidskracht binnen je organisatie. |
controlPointId | string | Koppel aan een controlepunt uit het normenkader. |
verstrekkingMethod | string | e_handtekening, natte_handtekening of verzendbewijs. |
verstrekkingDate | string | Datum van verstrekking (YYYY-MM-DD). |
Voorbeeld
curl -X POST "https://wtta-dossier.nl/api/v1/documents" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-F "file=@paspoort.pdf" \
-F "type=id_bewijs" \
-F "title=Paspoort Jan Kowalski" \
-F "workerId=01JZX…"
Respons
201 Created
{
"document": { "id": "01JZY…", "type": "id_bewijs", … },
"completedTasks": [ { "id": "01JZZ…", "title": "ID-check uitvoeren: Jan Kowalski", … } ]
}
PATCH /api/v1/documents/{id}
Documentmetadata bijwerken
Werkt metadata bij (JSON, geen bestand). Dezelfde velden als bij de upload, behalve file.
Voorbeeld
curl -X PATCH "https://wtta-dossier.nl/api/v1/documents/01JZY…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "expiryDate": "2031-01-01" }'
Respons
{ "document": { … }, "completedTasks": [] }
GET /api/v1/documents/{id}/download
Downloadlink opvragen
Geeft een tijdelijke, ondertekende downloadlink naar het bestand. De link verloopt na korte tijd; vraag per download een nieuwe op.
Voorbeeld
curl "https://wtta-dossier.nl/api/v1/documents/01JZY…/download" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{ "url": "https://…/paspoort.pdf?X-Amz-Signature=…" }
DELETE /api/v1/documents/{id}
Document archiveren
Soft delete: het bestand blijft in de kluis vanwege de wettelijke bewaartermijn.
Voorbeeld
curl -X DELETE "https://wtta-dossier.nl/api/v1/documents/01JZY…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{ "ok": true }
Clients (inleners)
Inleners zijn de bedrijven waar arbeidskrachten worden geplaatst.
GET /api/v1/clients
Inleners ophalen
Queryparameters
| Veld | Type | Omschrijving |
search | string | Zoekt in de bedrijfsnaam. |
limit | number | Aantal resultaten per pagina (standaard 25, maximaal 200). |
offset | number | Aantal resultaten dat wordt overgeslagen (standaard 0). |
Voorbeeld
curl "https://wtta-dossier.nl/api/v1/clients" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{
"clients": [
{
"id": "01JZA…",
"name": "Bouwbedrijf Jansen BV",
"kvk_number": "12345678",
"contact_name": "P. Jansen",
"contact_email": "p.jansen@example.com",
"created_at": "2026-02-01T08:00:00.000Z"
}
],
"total": 1
}
GET /api/v1/clients/{id}
Inlener ophalen
Inclusief alle plaatsingen bij deze inlener.
Voorbeeld
curl "https://wtta-dossier.nl/api/v1/clients/01JZA…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{ "client": { … }, "placements": [ { "id": "01JZB…", "worker_name": "Jan Kowalski", … } ] }
POST /api/v1/clients
Inlener aanmaken
Body
| Veld | Type | Omschrijving |
name verplicht | string | Bedrijfsnaam. |
kvkNumber | string | null | KvK-nummer. |
contactName | string | null | Naam contactpersoon. |
contactEmail | string | null | E-mailadres contactpersoon. |
notes | string | null | Vrije notities. |
Voorbeeld
curl -X POST "https://wtta-dossier.nl/api/v1/clients" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "name": "Bouwbedrijf Jansen BV", "kvkNumber": "12345678" }'
Respons
201 Created
{ "client": { "id": "01JZA…", "name": "Bouwbedrijf Jansen BV", … } }
PATCH /api/v1/clients/{id}
Inlener bijwerken
Voorbeeld
curl -X PATCH "https://wtta-dossier.nl/api/v1/clients/01JZA…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "contactName": "M. de Vries" }'
Respons
{ "client": { … } }
DELETE /api/v1/clients/{id}
Inlener archiveren
Voorbeeld
curl -X DELETE "https://wtta-dossier.nl/api/v1/clients/01JZA…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{ "ok": true }
Placements (plaatsingen)
Een plaatsing koppelt een arbeidskracht aan een inlener voor een bepaalde periode.
GET /api/v1/placements
Plaatsingen ophalen
Queryparameters
| Veld | Type | Omschrijving |
clientId | string | Alleen plaatsingen bij deze inlener. |
workerId | string | Alleen plaatsingen van deze arbeidskracht. |
limit | number | Aantal resultaten per pagina (standaard 25, maximaal 200). |
offset | number | Aantal resultaten dat wordt overgeslagen (standaard 0). |
Voorbeeld
curl "https://wtta-dossier.nl/api/v1/placements?workerId=01JZX…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{
"placements": [
{
"id": "01JZB…",
"client_id": "01JZA…",
"worker_id": "01JZX…",
"client_name": "Bouwbedrijf Jansen BV",
"worker_name": "Jan Kowalski",
"location": "Utrecht",
"start_date": "2026-03-01",
"end_date": null
}
],
"total": 1
}
POST /api/v1/placements
Plaatsing registreren
Body
| Veld | Type | Omschrijving |
clientId verplicht | string | Id van de inlener. |
workerId verplicht | string | Id van de arbeidskracht. |
startDate verplicht | string | Startdatum (YYYY-MM-DD). |
endDate | string | null | Einddatum (YYYY-MM-DD). |
location | string | null | Werklocatie. |
Voorbeeld
curl -X POST "https://wtta-dossier.nl/api/v1/placements" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{
"clientId": "01JZA…",
"workerId": "01JZX…",
"startDate": "2026-03-01",
"location": "Utrecht"
}'
Respons
201 Created
{ "placement": { "id": "01JZB…", … } }
PATCH /api/v1/placements/{id}
Plaatsing bijwerken
Alleen location, startDate en endDate kunnen worden gewijzigd.
Voorbeeld
curl -X PATCH "https://wtta-dossier.nl/api/v1/placements/01JZB…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "endDate": "2026-09-30" }'
Respons
{ "placement": { … } }
Tasks (taken)
De takenlijst bevat handmatige taken én taken die automatisch worden gegenereerd uit het normenkader en de dossiers van arbeidskrachten. Bij het ophalen van de lijst worden periodieke taken eerst geactualiseerd.
GET /api/v1/tasks
Taken ophalen
Queryparameters
| Veld | Type | Omschrijving |
status | string | Filter: open of afgerond. |
workerId | string | Alleen taken gekoppeld aan deze arbeidskracht. |
limit | number | Aantal resultaten per pagina (standaard 25, maximaal 200). |
offset | number | Aantal resultaten dat wordt overgeslagen (standaard 0). |
Voorbeeld
curl "https://wtta-dossier.nl/api/v1/tasks?status=open" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{
"tasks": [
{
"id": "01JZZ…",
"title": "VOG aanvragen",
"status": "open",
"source": "handmatig",
"due_date": "2026-08-01",
"assignee_user_id": "abc…",
"assignee_name": "A. de Boer",
"worker_id": null,
"recurrence": "none",
"completed_at": null
}
],
"total": 1
}
GET /api/v1/tasks/{id}
Taak ophalen
Voorbeeld
curl "https://wtta-dossier.nl/api/v1/tasks/01JZZ…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
Respons
{ "task": { "id": "01JZZ…", "title": "VOG aanvragen", … } }
POST /api/v1/tasks
Taak aanmaken
Body
| Veld | Type | Omschrijving |
title verplicht | string | Titel van de taak. |
description | string | null | Toelichting. |
dueDate | string | null | Deadline (YYYY-MM-DD). |
assigneeUserId | string | null | Gebruikers-id van een lid van je organisatie. |
workerId | string | null | Koppel aan een arbeidskracht. |
recurrence | string | none, monthly, quarterly, halfyearly of yearly (standaard none). |
Voorbeeld
curl -X POST "https://wtta-dossier.nl/api/v1/tasks" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "title": "VOG aanvragen", "dueDate": "2026-08-01" }'
Respons
201 Created
{ "task": { "id": "01JZZ…", "status": "open", "source": "handmatig", … } }
PATCH /api/v1/tasks/{id}
Taak bijwerken of afronden
Zet status op afgerond om een taak af te ronden (completed_at wordt gevuld) of terug op open om te heropenen. Andere velden zoals title, dueDate en assigneeUserId kunnen tegelijk worden bijgewerkt.
Voorbeeld
curl -X PATCH "https://wtta-dossier.nl/api/v1/tasks/01JZZ…" \
-H "Authorization: Bearer nd_live_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" \
-H "Content-Type: application/json" \
-d '{ "status": "afgerond" }'
Respons
{ "task": { "status": "afgerond", "completed_at": "2026-07-16T14:03:00.000Z", … } }
Hulp nodig?
Loop je ergens tegenaan? Neem contact op, dan denken we graag mee over je integratie.