WTTA-Dossier

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.

StatusCodeBetekenis
400validation_errorDe aanvraag is ongeldig; de message beschrijft per veld wat er mist.
401unauthorizedGeen, ongeldige of ingetrokken API-sleutel.
402payment_requiredSchrijfacties vereisen een actief abonnement of lopende proefperiode.
403forbiddenDe actie is niet toegestaan.
404not_foundDe resource bestaat niet of hoort bij een andere organisatie.
409conflictDe aanvraag botst met de huidige staat van de resource.
413payload_too_largeHet geüploade bestand is te groot.
429rate_limitedTe veel aanvragen; zie de X-RateLimit-headers.
500internal_errorOnverwachte 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

VeldTypeOmschrijving
searchstringZoekt in voornaam, achternaam en e-mailadres.
nationalitystringFilter: nl, eu of derde_land.
housingstringFilter op huisvesting via het bureau: ja of nee.
contractstringFilter op contracttype.
limitnumberAantal resultaten per pagina (standaard 25, maximaal 200).
offsetnumberAantal 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

VeldTypeOmschrijving
firstName verplichtstringVoornaam.
lastName verplichtstringAchternaam.
nationalityCategory verplichtstringnl, eu of derde_land.
employmentStartstring | nullStartdatum dienstverband (YYYY-MM-DD).
employmentEndstring | nullEinddatum dienstverband (YYYY-MM-DD).
contractTypestring | nullContracttype, vrij tekstveld.
housingProvidedbooleanHuisvesting via het bureau (standaard false).
emailstring | nullE-mailadres.
notesstring | nullVrije 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

VeldTypeOmschrijving
typestringFilter op documenttype. Mogelijke waarden: vog_rp, sna_certificaat, snf_certificaat, id_bewijs, werkvergunning, arbeidsovereenkomst, loonstrook, belastingverklaring, inspectierapport, betaalbewijs, ketenverklaring, overig.
workerIdstringAlleen documenten van deze arbeidskracht.
searchstringZoekt in titel en bestandsnaam.
limitnumberAantal resultaten per pagina (standaard 25, maximaal 200).
offsetnumberAantal 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

VeldTypeOmschrijving
file verplichtbestandHet bestand zelf (multipart-veld).
typestringDocumenttype (standaard overig). Mogelijke waarden: vog_rp, sna_certificaat, snf_certificaat, id_bewijs, werkvergunning, arbeidsovereenkomst, loonstrook, belastingverklaring, inspectierapport, betaalbewijs, ketenverklaring, overig.
titlestringTitel (standaard de bestandsnaam).
expiryDatestringVervaldatum (YYYY-MM-DD).
workerIdstringKoppel aan een arbeidskracht binnen je organisatie.
controlPointIdstringKoppel aan een controlepunt uit het normenkader.
verstrekkingMethodstringe_handtekening, natte_handtekening of verzendbewijs.
verstrekkingDatestringDatum 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

VeldTypeOmschrijving
searchstringZoekt in de bedrijfsnaam.
limitnumberAantal resultaten per pagina (standaard 25, maximaal 200).
offsetnumberAantal 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

VeldTypeOmschrijving
name verplichtstringBedrijfsnaam.
kvkNumberstring | nullKvK-nummer.
contactNamestring | nullNaam contactpersoon.
contactEmailstring | nullE-mailadres contactpersoon.
notesstring | nullVrije 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

VeldTypeOmschrijving
clientIdstringAlleen plaatsingen bij deze inlener.
workerIdstringAlleen plaatsingen van deze arbeidskracht.
limitnumberAantal resultaten per pagina (standaard 25, maximaal 200).
offsetnumberAantal 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

VeldTypeOmschrijving
clientId verplichtstringId van de inlener.
workerId verplichtstringId van de arbeidskracht.
startDate verplichtstringStartdatum (YYYY-MM-DD).
endDatestring | nullEinddatum (YYYY-MM-DD).
locationstring | nullWerklocatie.

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

VeldTypeOmschrijving
statusstringFilter: open of afgerond.
workerIdstringAlleen taken gekoppeld aan deze arbeidskracht.
limitnumberAantal resultaten per pagina (standaard 25, maximaal 200).
offsetnumberAantal 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

VeldTypeOmschrijving
title verplichtstringTitel van de taak.
descriptionstring | nullToelichting.
dueDatestring | nullDeadline (YYYY-MM-DD).
assigneeUserIdstring | nullGebruikers-id van een lid van je organisatie.
workerIdstring | nullKoppel aan een arbeidskracht.
recurrencestringnone, 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.