Overstappen naar een andere assessmentleverancier gaat mis op de koppelingen, niet op de tool. Bevries je scoringsregels, exporteer met het kandidaat-ID uit je ATS als sleutel, test de hele keten in staging en spreek vooraf af bij welke daling in afrondingspercentage je terugrolt. Dan merkt je pipeline er niets van.
Je hiring funnel loopt in elke fase door je assessmentplatform. Uitnodigingen vanuit het ATS, kandidaten die de test afronden, scores die terugschrijven naar het kandidaatdossier, shortlists en het inplannen van gesprekken. Breekt er ergens een schakel, dan zie je dat binnen een paar dagen terug in je cijfers. Meestal als een meetbare daling in het afrondingspercentage, vertraagde shortlists of rapportages die niet meer kloppen.
Dit artikel loopt de hele migratie door. Voorwaarden en afhankelijkheden, exportschema's en veldmapping, authenticatiepatronen met voorbeeldrequests, testcases voor staging en de compliance-eisen die bepalen hoe je de migratie inricht. Gebruik het als QA-draaiboek naast de onboardingdocumentatie van je nieuwe leverancier.
Voordat je één regel migratiecode schrijft, leg je vast welke data precies meegaat. Bij een migratie van een assessmentplatform gaat het meestal om deze objecten.
candidate_id, de externe candidate_uuid, taalvoorkeur en toestemmingsstatusINVITED, IN_PROGRESS, COMPLETED, EXPIRED, WITHDRAWN)Voor alles wat hier niet in staat neem je een expliciet besluit. Meenemen, weggooien of archiveren.
Hier ontstaat bij de meeste migraties stille datavervuiling. Je ATS, je assessmentplatform en je identity provider kennen alle drie een eigen identifier toe aan dezelfde kandidaat, en die komen niet overeen.
Leg de hiërarchie vast voordat je mappinglogica schrijft.
candidate_id. De stabiele interne sleutel in je systeem van registratie. Gebruik deze als primaire join keycandidate_uuid. Een UUID die het assessmentplatform toekent. Sla die tijdens de migratie op als custom veld in je ATSJe ATS is de bron van waarheid voor identiteit. Elk geïmporteerd record hoort het oorspronkelijke ATS candidate_id mee te dragen. Heeft je huidige leverancier dat veld nooit opgeslagen, dan heb je eerst een reconciliatiequery nodig op e-mailadres plus uitnodigingstijdstip voordat je historie betrouwbaar kunt koppelen.
Rond dit af voordat je aan de export of de API-configuratie begint.
ATS → Assessmentplatform
├─ Uitnodigingen (ATS start de uitnodiging via API of webhook)
├─ Afrondingen (assessmentplatform POST een completion-event naar de ATS-webhook)
├─ Rapport ophalen (ATS doet een GET of toont een ingesloten URL)
├─ Scores terugschrijven (assessmentplatform PATCH kandidaatvelden in het ATS)
└─ Gesprekken inplannen (planningssysteem leest de shortlist uit het ATS)
Breekt er één knooppunt, dan verslechtert een stap verderop stilletjes zonder dat er een foutmelding komt.
Een schone migratie houdt je pipelineprestaties intact. Dat is niet abstract. Teleperformance bespaart met Selection Lab 15 minuten per sollicitant, en dat soort winst wil je tijdens een overstap niet weggeven. Leg voor dag 1 tot en met dag 14 na de cutover expliciete meetpunten vast.
| Meetpunt | Nulmeting (14 dagen ervoor) | Stopcriterium |
|---|---|---|
| Afrondingspercentage assessment | Meten en vastleggen | Daling > 5 procentpunt |
| Uitnodiging-naar-start | Meten en vastleggen | Daling > 8 procentpunt |
| Geslaagde rapportsynchronisatie | ~100% | Onder 98% |
| Mislukte webhookleveringen | < 1% | Boven 3% |
| Gemiddelde doorlooptijd naar volgende stap | Meten en vastleggen | Toename > 24 uur |
Vraag je export in JSON of in gestructureerde CSV met vaste kolomkoppen. Vermijd platformeigen exportformaten zoals .xlsm of eigen XML, want veldnamen en waardeformaten verschillen per leveranciersversie. JSON werkt beter voor geneste structuren zoals scoreobjecten met meerdere dimensies. CSV is prettig voor platte kandidaat- en sessierecords die je snel in een spreadsheet wilt controleren.
Zet in je exportverzoek expliciet deze eisen.
2025-11-14T09:30:00+00:00null of het veld helemaal weglaten"COMPLETED" en niet "Afgerond"De schema's hieronder zijn voorbeelden. Pas de veldnamen aan op het API-contract van je eigen leveranciers.
Kandidaat
{
"ats_candidate_id": "ATS-78432",
"external_candidate_uuid": "c3f1a2b4-84d2-4e9a-b7c1-0f3e2d1a9b56",
"email": "[email protected]",
"preferred_language": "nl",
"consent_given_at": "2025-10-01T14:22:00+00:00",
"consent_version": "v2.1",
"data_retention_expires_at": "2027-10-01T00:00:00+00:00"
}
Assessmentsessie
{
"session_id": "sess_9f2e1c3d",
"ats_candidate_id": "ATS-78432",
"external_candidate_uuid": "c3f1a2b4-84d2-4e9a-b7c1-0f3e2d1a9b56",
"assessment_id": "asmt_cognitive_v3",
"assessment_version": "3.2.1",
"rule_version": "rule_2025q4",
"scoring_model_version": "sm_2025.2",
"status": "COMPLETED",
"invited_at": "2025-10-02T08:00:00+00:00",
"started_at": "2025-10-02T09:15:00+00:00",
"completed_at": "2025-10-02T09:48:00+00:00",
"locale": "nl-NL"
}
Assessmentresultaat
{
"session_id": "sess_9f2e1c3d",
"ats_candidate_id": "ATS-78432",
"assessment_version": "3.2.1",
"scoring_model_version": "sm_2025.2",
"dimensions": {
"verbal_reasoning": { "raw_score": 28, "percentile": 72 },
"numerical_reasoning": { "raw_score": 31, "percentile": 81 },
"conscientiousness": { "raw_score": 44, "percentile": 65 }
},
"composite_score": 74.2,
"composite_percentile": 76
}
Match op functieprofiel
{
"session_id": "sess_9f2e1c3d",
"role_profile_id": "rp_teamleider_logistiek_v2",
"role_profile_version": "v2.0",
"match_score": 0.81,
"recommendation": "ADVANCE",
"generated_at": "2025-10-02T10:00:00+00:00"
}
Auditgebeurtenis
{
"event_id": "evt_a1b2c3d4",
"event_type": "REPORT_ACCESSED",
"actor_type": "RECRUITER",
"actor_id": "usr_recruiter_042",
"session_id": "sess_9f2e1c3d",
"ats_candidate_id": "ATS-78432",
"occurred_at": "2025-10-03T11:05:00+00:00"
}
Label elk geïmporteerd historisch record met assessment_version, rule_version en scoring_model_version. Zonder die labels mengt je rapportage scores die onder verschillende normgroepen of scoringsgewichten zijn berekend, en dan zeggen je gemiddelden niets meer. Een kandidaat die op sm_2024.1 in het 72e percentiel scoorde, is niet zinvol te vergelijken met iemand die onder sm_2025.2 is beoordeeld, tenzij je rapportage op versie kan filteren.
Bij het terugzetten van matchscores geldt hetzelfde. Die zijn berekend tegen een specifieke role_profile_version. Heeft je oude leverancier functieprofielen tussentijds aangepast, dan heb je een versiebewuste query nodig die elke sessie koppelt aan het profiel dat gold op het moment van completed_at.
Artikel 20 AVG gaat over persoonsgegevens die de kandidaat zelf heeft verstrekt of die zijn ontstaan door zijn eigen handelen. Oordelen en voorspellingen die het platform zelf produceert, bijvoorbeeld een AI-afgeleide aanbeveling, vallen daar mogelijk buiten omdat ze de beoordeling van de verwerkingsverantwoordelijke zijn en geen activiteitsdata. Vraag je functionaris gegevensbescherming welke velden je leverancier als overdraagbaar beschouwt en welke als afgeleid. Dat verschil bepaalt wat je juridisch mag importeren en wat je opnieuw moet laten genereren.
Drie patronen dekken vrijwel alle koppelingen tussen een assessmentplatform en een ATS.
completion-event naar een endpoint in je ATS. Dit is het snelst voor bijna-realtime scoresynchronisatieGET /assessment-sessions/{session_id}/results. Simpeler te bouwen, maar met vertragingDe meeste productieomgevingen combineren patroon 1 voor afrondingen, patroon 2 voor het ophalen van rapporten en patroon 3 als nachtelijke controle op gemiste events.
| Methode | Typisch gebruik | Aandachtspunt bij migratie |
|---|---|---|
| OAuth 2.0 client credentials | Server-naar-server scoresynchronisatie en rapporten ophalen | Roteer client_id en client_secret vóór de cutover en leg de benodigde scopes expliciet vast |
| OAuth 2.0 authorization code | Rapportinzage door een ingelogde recruiter | Test de token-refresh in staging voordat je live gaat |
| API-sleutel | Webhookregistratie en eenvoudige REST-pulls | Roteer de sleutel tegelijk in het ATS en in het assessmentplatform en gebruik de oude sleutel daarna niet meer |
| Ondertekend webhook-secret (HMAC-SHA256) | Verificatie van de payload | Genereer een nieuw secret en werk de webhookhandler in je ATS bij vóór je het nieuwe endpoint activeert |
Checklist voor het roteren van credentials.
assessments:read, reports:read en candidates:writeDe voorbeelden hieronder gebruiken fictieve base-URL's en veldnamen. Vervang ze door het echte API-contract van je leverancier.
POST /api/v1/invitations, een uitnodiging aanmaken met idempotency key
POST /api/v1/invitations HTTP/1.1
Host: assessment.provider.example
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: inv_ATS78432_asmt_cognitive_v3_20251002
{
"ats_candidate_id": "ATS-78432",
"email": "[email protected]",
"assessment_id": "asmt_cognitive_v3",
"locale": "nl-NL",
"expires_at": "2025-10-09T23:59:00+00:00",
"callback_url": "https://jouw-ats.example/webhooks/assessment"
}
GET /api/v1/assessment-sessions/{session_id}/results
GET /api/v1/assessment-sessions/sess_9f2e1c3d/results HTTP/1.1
Host: assessment.provider.example
Authorization: Bearer {access_token}
Accept: application/json
POST /webhooks/assessment-complete, de payload die binnenkomt op je ATS-endpoint
{
"event_id": "evt_a1b2c3d4",
"event_type": "ASSESSMENT_COMPLETED",
"session_id": "sess_9f2e1c3d",
"ats_candidate_id": "ATS-78432",
"completed_at": "2025-10-02T09:48:00+00:00",
"report_url": "https://assessment.provider.example/reports/sess_9f2e1c3d",
"composite_score": 74.2,
"recommendation": "ADVANCE"
}
PATCH /ats/v2/candidates/{ats_candidate_id}/attributes, de score terugschrijven naar je ATS
PATCH /ats/v2/candidates/ATS-78432/attributes HTTP/1.1
Host: jouw-ats.example
Authorization: Bearer {ats_access_token}
Content-Type: application/json
{
"assessment_session_id": "sess_9f2e1c3d",
"assessment_version": "3.2.1",
"scoring_model_version": "sm_2025.2",
"composite_score": 74.2,
"composite_percentile": 76,
"recommendation": "ADVANCE",
"score_synced_at": "2025-10-02T10:01:00+00:00"
}
Idempotency-Key op elke POST /invitations en POST /sessions. De sleutel moet uniek zijn per combinatie van kandidaat en assessment, bijvoorbeeld inv_{ats_candidate_id}_{assessment_id}_{datum}.event_id plus session_id. Bewaar verwerkte event_id-waarden minstens 72 uur.completed_at verpest je funnelanalyse, vooral de doorlooptijd naar de volgende stap.Voordat je één testcase draait, controleer je of je het volgende hebt.
Test je cutover nooit op productiedata. Zet historische scores pas in je productie-ATS als de stagingrun alle verificatiestappen heeft doorstaan.
Draai deze zeven tests in volgorde. Elke test moet slagen voordat je aan de volgende begint.
ats_candidate_id correct oplost en of scorevelden vullen zonder bestaande data te overschrijven200 OK teruggeeftTC-01, standaardflow. Trigger, nodig een testkandidaat uit vanuit het ATS. Verwacht, de kandidaat ontvangt de uitnodiging, rondt het assessment af en je ATS-endpoint ontvangt binnen 60 seconden een ASSESSMENT_COMPLETED-event. Het kandidaatdossier wordt bijgewerkt met composite_score, recommendation en report_url. Geslaagd als alle drie de velden gevuld zijn en er geen dubbele sessie is ontstaan.
TC-02, idempotente heruitnodiging. Trigger, stuur dezelfde POST /invitations twee keer met identieke Idempotency-Key. Verwacht, de leverancier geeft beide keren dezelfde session_id terug en er bestaat één sessie. Geslaagd als het tweede verzoek 200 of 409 met het oorspronkelijke sessieobject teruggeeft.
TC-03, historische import met versielabels. Trigger, importeer vijftig historische sessies, elk gelabeld met assessment_version en scoring_model_version. Verwacht, alle vijftig records koppelen aan bestaande kandidaatdossiers, scorevelden vullen correct en de versielabels zijn zichtbaar in je rapportagefilters. Geslaagd als er geen enkel onopgelost ats_candidate_id is en geen scoreveld leeg blijft waar de bron wel een waarde had.
TC-04, meertalige afname. Trigger, nodig een testkandidaat uit met locale: nl-NL en rond het assessment af. Verwacht, de rapportage komt terug met locale: nl-NL, de inhoud is Nederlands en je ATS ontvangt een report_language dat overeenkomt. Geslaagd als de rapporttaal klopt en er niet stilzwijgend wordt teruggevallen op Engels.
TC-05, toestemming en bewaartermijn. Trigger, maak een uitnodiging aan voor een kandidaat met een specifieke toestemmingsversie, rond het assessment af en vraag het rapport op. Verwacht, de toestemming staat in het auditlog met consent_version, consent_given_at en data_retention_expires_at. Geslaagd als alle drie de velden zowel in het auditlog van het platform als in het ATS-dossier staan.
Draai na de eerste 48 uur in productie deze controles op de logs van beide leveranciers, voor de groep kandidaten die in beide systemen voorkomt.
COMPLETED. Het totaal op het nieuwe platform moet binnen 2% liggen van wat je op basis van het uitnodigingsvolume verwachtcomposite_score. Die hoort niet meer dan 0,5 standaarddeviatie te verschuiven ten opzichte van de nulmeting van 14 dagen. Een grotere verschuiving wijst eerder op een verkeerde scoringsmodelversie dan op andere kandidatenreport_url. Trek een steekproef van vijftig rapport-URL's en controleer of ze allemaal openen met geldige credentialsZakt het afrondingspercentage verder dan afgesproken, kijk naar de tabel met KPI-grenzen hierboven, dan rol je direct terug. Terugrollen betekent dat je de uitnodigingstrigger in je ATS weer naar de oude leverancier wijst, niet alleen dat je stopt met nieuwe uitnodigingen. Wijs vooraf een eigenaar aan die de eerste 72 uur bereikbaar is.
Kandidaat-ID's die niet matchen. Koppelen op e-mailadres gaat mis zodra een kandidaat tussen sollicitatie en import van mailadres wisselt. Koppel altijd op ats_candidate_id. Heeft je huidige leverancier dat veld nooit opgeslagen, bouw dan een reconciliatiequery op e-mailadres plus uitnodigingstijdstip met een tolerantievenster, en controleer handmatig elk geval waarin twee kandidaten hetzelfde adres delen.
Stille schemawijzigingen. Leveranciers passen veldnamen en enum-waarden aan zonder dat aan te kondigen. Een veld dat eerst status: "complete" was, wordt na een kleine versiestap status: "COMPLETED". Valideer alle binnenkomende webhookpayloads en uitgaande API-responses tegen een JSON Schema. Laat het hard falen bij een onverwachte waarde in plaats van velden stilletjes te laten wegvallen.
Dubbele score-updates. Zonder idempotente webhookafhandeling schrijft een retry van een ASSESSMENT_COMPLETED-event een tweede scorerecord weg, en dan weet niemand meer welke telt. Bewaar verwerkte event_id-waarden en weiger duplicaten vóór elke schrijfactie.
Verkeerde OAuth-scopes tijdens de cutover. Een client die is ingericht met assessments:write in plaats van assessments:read slaagt in je tests en faalt in productie op het moment dat er een leesactie wordt verwacht. Documenteer per integratiepatroon welke scopes nodig zijn en test in staging bewust met verkeerde scopes.
Klokverschil en tijdzones. Een leverancier die tijdstempels in lokale tijd teruggeeft zonder offset laat je funnelanalyse uren afwijken. Dwing ISO-8601 met expliciete UTC-offset af op alle velden en bouw een validatiestap die elke tijdstempel zonder tijdzone afkeurt of markeert.
Toestemming die op een ander moment komt. Bij een overstap verandert de toestemmingsflow die kandidaten te zien krijgen. Vraagt de nieuwe leverancier toestemming op een ander punt in de journey dan de oude, dan krijgt de kandidaat een onverwacht scherm en haakt een deel af. Teken de volgorde uit en test hem end-to-end in TC-05. Selection Lab vraagt toestemming voordat resultaten worden getoond en opnieuw voordat ze worden gedeeld, wat een bruikbaar model is voor waar je toestemmingsmomenten legt.
Historie importeren zonder versielabels. Doe je dat, dan mengt je rapportage scoreverdelingen van kandidaten die onder verschillende normgroepen zijn beoordeeld. Label elk geïmporteerd record met de drie versievelden uit het schema hierboven.
Gebroken deeplinks vanuit je ATS. Staat er in kandidaatdossiers een directe URL naar een assessmentsessie, dan werken die links na de overstap niet meer. Inventariseer vóór go-live alle ATS-velden waar zulke URL's in staan en vervang of redirect ze als onderdeel van de cutover, niet erna.
Rapportages die niet meer vergelijkbaar zijn. Je nieuwe leverancier gebruikt mogelijk andere eventnamen of berekent uitval in een andere funnelfase. Map de oude eventnamen expliciet op de nieuwe voordat je de koppeling afrondt, en controleer of je dashboards dezelfde KPI's opleveren. Een daling in uitval betekent alleen iets als je die uitval voor en na de overstap op dezelfde manier berekent.
Loopt er iets mis tijdens of na de cutover, volg dan deze route.
session_id, event_id en request_id erbijats_candidate_id, session_id en event_idWijs vóór de cutover iemand aan die mag beslissen om terug te rollen, zonder dat daar nog goedkeuring bij hoeft. Houd op de dag zelf het volgende continu open.
Zet dit in je exportverzoek aan de vertrekkende leverancier.
COMPLETED-sessies of alle sessiesVan assessmentleverancier wisselen zonder je hiring pipeline te verstoren is een uitvoeringsvraagstuk, geen strategievraagstuk. De patronen hierboven geven je een concreet QA-kader om te controleren of elke stap in de funnel werkt voordat je definitief overgaat. Draai de testcases, bewaak je KPI-grenzen en houd de eigenaar van het terugrolbesluit bereikbaar.
Reken op 2 tot 10 weken van eerste exportaanvraag tot go-live, afhankelijk van hoeveel historie je meeneemt en hoe diep de ATS-koppeling gaat. De export bij je vertrekkende leverancier is meestal de traagste stap, dus vraag die doorlooptijd schriftelijk op voordat je een cutoverdatum vastlegt.
Ruwe kandidaat- en sessiedata valt onder artikel 20 AVG en is in principe overdraagbaar. Scores en aanbevelingen die het platform zelf heeft berekend, kunnen daarbuiten vallen omdat ze het oordeel van de verwerkingsverantwoordelijke zijn. Laat je functionaris gegevensbescherming per veld bepalen wat overdraagbaar is en wat je opnieuw moet genereren.
Vier dingen. Kandidaten koppelen op e-mailadres in plaats van op het kandidaat-ID uit je ATS, historie importeren zonder versielabels, webhooks die niet dedupliceren en gebroken deeplinks in bestaande kandidaatdossiers. Alle vier zijn stille fouten, dus je ziet ze pas terug in je rapportage.
Spreek het getal vooraf af. Een gangbare grens is een daling van het afrondingspercentage met meer dan 5 procentpunt ten opzichte van de nulmeting van 14 dagen, of een slagingspercentage van webhookleveringen onder 98%. Terugrollen betekent dat je de uitnodigingstrigger in je ATS weer naar de oude leverancier wijst.
Niet als je de toestemmingsflow en de uitnodigingsmail meetest voordat je live gaat. De meeste uitval bij een overstap komt niet van het assessment zelf, maar van een onverwacht toestemmingsscherm of een deeplink die niet meer werkt. Test beide in staging via TC-05.
.png)
Overstappen naar een andere assessmentleverancier gaat mis op de koppelingen, niet op de tool. Bevries je scoringsregels, exporteer met het kandidaat-ID uit je ATS als sleutel, test de hele keten in staging en spreek vooraf af bij welke daling in afrondingspercentage je terugrolt. Dan merkt je pipeline er niets van.
Je hiring funnel loopt in elke fase door je assessmentplatform. Uitnodigingen vanuit het ATS, kandidaten die de test afronden, scores die terugschrijven naar het kandidaatdossier, shortlists en het inplannen van gesprekken. Breekt er ergens een schakel, dan zie je dat binnen een paar dagen terug in je cijfers. Meestal als een meetbare daling in het afrondingspercentage, vertraagde shortlists of rapportages die niet meer kloppen.
Dit artikel loopt de hele migratie door. Voorwaarden en afhankelijkheden, exportschema's en veldmapping, authenticatiepatronen met voorbeeldrequests, testcases voor staging en de compliance-eisen die bepalen hoe je de migratie inricht. Gebruik het als QA-draaiboek naast de onboardingdocumentatie van je nieuwe leverancier.
Voordat je één regel migratiecode schrijft, leg je vast welke data precies meegaat. Bij een migratie van een assessmentplatform gaat het meestal om deze objecten.
candidate_id, de externe candidate_uuid, taalvoorkeur en toestemmingsstatusINVITED, IN_PROGRESS, COMPLETED, EXPIRED, WITHDRAWN)Voor alles wat hier niet in staat neem je een expliciet besluit. Meenemen, weggooien of archiveren.
Hier ontstaat bij de meeste migraties stille datavervuiling. Je ATS, je assessmentplatform en je identity provider kennen alle drie een eigen identifier toe aan dezelfde kandidaat, en die komen niet overeen.
Leg de hiërarchie vast voordat je mappinglogica schrijft.
candidate_id. De stabiele interne sleutel in je systeem van registratie. Gebruik deze als primaire join keycandidate_uuid. Een UUID die het assessmentplatform toekent. Sla die tijdens de migratie op als custom veld in je ATSJe ATS is de bron van waarheid voor identiteit. Elk geïmporteerd record hoort het oorspronkelijke ATS candidate_id mee te dragen. Heeft je huidige leverancier dat veld nooit opgeslagen, dan heb je eerst een reconciliatiequery nodig op e-mailadres plus uitnodigingstijdstip voordat je historie betrouwbaar kunt koppelen.
Rond dit af voordat je aan de export of de API-configuratie begint.
ATS → Assessmentplatform
├─ Uitnodigingen (ATS start de uitnodiging via API of webhook)
├─ Afrondingen (assessmentplatform POST een completion-event naar de ATS-webhook)
├─ Rapport ophalen (ATS doet een GET of toont een ingesloten URL)
├─ Scores terugschrijven (assessmentplatform PATCH kandidaatvelden in het ATS)
└─ Gesprekken inplannen (planningssysteem leest de shortlist uit het ATS)
Breekt er één knooppunt, dan verslechtert een stap verderop stilletjes zonder dat er een foutmelding komt.
Een schone migratie houdt je pipelineprestaties intact. Dat is niet abstract. Teleperformance bespaart met Selection Lab 15 minuten per sollicitant, en dat soort winst wil je tijdens een overstap niet weggeven. Leg voor dag 1 tot en met dag 14 na de cutover expliciete meetpunten vast.
| Meetpunt | Nulmeting (14 dagen ervoor) | Stopcriterium |
|---|---|---|
| Afrondingspercentage assessment | Meten en vastleggen | Daling > 5 procentpunt |
| Uitnodiging-naar-start | Meten en vastleggen | Daling > 8 procentpunt |
| Geslaagde rapportsynchronisatie | ~100% | Onder 98% |
| Mislukte webhookleveringen | < 1% | Boven 3% |
| Gemiddelde doorlooptijd naar volgende stap | Meten en vastleggen | Toename > 24 uur |
Vraag je export in JSON of in gestructureerde CSV met vaste kolomkoppen. Vermijd platformeigen exportformaten zoals .xlsm of eigen XML, want veldnamen en waardeformaten verschillen per leveranciersversie. JSON werkt beter voor geneste structuren zoals scoreobjecten met meerdere dimensies. CSV is prettig voor platte kandidaat- en sessierecords die je snel in een spreadsheet wilt controleren.
Zet in je exportverzoek expliciet deze eisen.
2025-11-14T09:30:00+00:00null of het veld helemaal weglaten"COMPLETED" en niet "Afgerond"De schema's hieronder zijn voorbeelden. Pas de veldnamen aan op het API-contract van je eigen leveranciers.
Kandidaat
{
"ats_candidate_id": "ATS-78432",
"external_candidate_uuid": "c3f1a2b4-84d2-4e9a-b7c1-0f3e2d1a9b56",
"email": "[email protected]",
"preferred_language": "nl",
"consent_given_at": "2025-10-01T14:22:00+00:00",
"consent_version": "v2.1",
"data_retention_expires_at": "2027-10-01T00:00:00+00:00"
}
Assessmentsessie
{
"session_id": "sess_9f2e1c3d",
"ats_candidate_id": "ATS-78432",
"external_candidate_uuid": "c3f1a2b4-84d2-4e9a-b7c1-0f3e2d1a9b56",
"assessment_id": "asmt_cognitive_v3",
"assessment_version": "3.2.1",
"rule_version": "rule_2025q4",
"scoring_model_version": "sm_2025.2",
"status": "COMPLETED",
"invited_at": "2025-10-02T08:00:00+00:00",
"started_at": "2025-10-02T09:15:00+00:00",
"completed_at": "2025-10-02T09:48:00+00:00",
"locale": "nl-NL"
}
Assessmentresultaat
{
"session_id": "sess_9f2e1c3d",
"ats_candidate_id": "ATS-78432",
"assessment_version": "3.2.1",
"scoring_model_version": "sm_2025.2",
"dimensions": {
"verbal_reasoning": { "raw_score": 28, "percentile": 72 },
"numerical_reasoning": { "raw_score": 31, "percentile": 81 },
"conscientiousness": { "raw_score": 44, "percentile": 65 }
},
"composite_score": 74.2,
"composite_percentile": 76
}
Match op functieprofiel
{
"session_id": "sess_9f2e1c3d",
"role_profile_id": "rp_teamleider_logistiek_v2",
"role_profile_version": "v2.0",
"match_score": 0.81,
"recommendation": "ADVANCE",
"generated_at": "2025-10-02T10:00:00+00:00"
}
Auditgebeurtenis
{
"event_id": "evt_a1b2c3d4",
"event_type": "REPORT_ACCESSED",
"actor_type": "RECRUITER",
"actor_id": "usr_recruiter_042",
"session_id": "sess_9f2e1c3d",
"ats_candidate_id": "ATS-78432",
"occurred_at": "2025-10-03T11:05:00+00:00"
}
Label elk geïmporteerd historisch record met assessment_version, rule_version en scoring_model_version. Zonder die labels mengt je rapportage scores die onder verschillende normgroepen of scoringsgewichten zijn berekend, en dan zeggen je gemiddelden niets meer. Een kandidaat die op sm_2024.1 in het 72e percentiel scoorde, is niet zinvol te vergelijken met iemand die onder sm_2025.2 is beoordeeld, tenzij je rapportage op versie kan filteren.
Bij het terugzetten van matchscores geldt hetzelfde. Die zijn berekend tegen een specifieke role_profile_version. Heeft je oude leverancier functieprofielen tussentijds aangepast, dan heb je een versiebewuste query nodig die elke sessie koppelt aan het profiel dat gold op het moment van completed_at.
Artikel 20 AVG gaat over persoonsgegevens die de kandidaat zelf heeft verstrekt of die zijn ontstaan door zijn eigen handelen. Oordelen en voorspellingen die het platform zelf produceert, bijvoorbeeld een AI-afgeleide aanbeveling, vallen daar mogelijk buiten omdat ze de beoordeling van de verwerkingsverantwoordelijke zijn en geen activiteitsdata. Vraag je functionaris gegevensbescherming welke velden je leverancier als overdraagbaar beschouwt en welke als afgeleid. Dat verschil bepaalt wat je juridisch mag importeren en wat je opnieuw moet laten genereren.
Drie patronen dekken vrijwel alle koppelingen tussen een assessmentplatform en een ATS.
completion-event naar een endpoint in je ATS. Dit is het snelst voor bijna-realtime scoresynchronisatieGET /assessment-sessions/{session_id}/results. Simpeler te bouwen, maar met vertragingDe meeste productieomgevingen combineren patroon 1 voor afrondingen, patroon 2 voor het ophalen van rapporten en patroon 3 als nachtelijke controle op gemiste events.
| Methode | Typisch gebruik | Aandachtspunt bij migratie |
|---|---|---|
| OAuth 2.0 client credentials | Server-naar-server scoresynchronisatie en rapporten ophalen | Roteer client_id en client_secret vóór de cutover en leg de benodigde scopes expliciet vast |
| OAuth 2.0 authorization code | Rapportinzage door een ingelogde recruiter | Test de token-refresh in staging voordat je live gaat |
| API-sleutel | Webhookregistratie en eenvoudige REST-pulls | Roteer de sleutel tegelijk in het ATS en in het assessmentplatform en gebruik de oude sleutel daarna niet meer |
| Ondertekend webhook-secret (HMAC-SHA256) | Verificatie van de payload | Genereer een nieuw secret en werk de webhookhandler in je ATS bij vóór je het nieuwe endpoint activeert |
Checklist voor het roteren van credentials.
assessments:read, reports:read en candidates:writeDe voorbeelden hieronder gebruiken fictieve base-URL's en veldnamen. Vervang ze door het echte API-contract van je leverancier.
POST /api/v1/invitations, een uitnodiging aanmaken met idempotency key
POST /api/v1/invitations HTTP/1.1
Host: assessment.provider.example
Authorization: Bearer {access_token}
Content-Type: application/json
Idempotency-Key: inv_ATS78432_asmt_cognitive_v3_20251002
{
"ats_candidate_id": "ATS-78432",
"email": "[email protected]",
"assessment_id": "asmt_cognitive_v3",
"locale": "nl-NL",
"expires_at": "2025-10-09T23:59:00+00:00",
"callback_url": "https://jouw-ats.example/webhooks/assessment"
}
GET /api/v1/assessment-sessions/{session_id}/results
GET /api/v1/assessment-sessions/sess_9f2e1c3d/results HTTP/1.1
Host: assessment.provider.example
Authorization: Bearer {access_token}
Accept: application/json
POST /webhooks/assessment-complete, de payload die binnenkomt op je ATS-endpoint
{
"event_id": "evt_a1b2c3d4",
"event_type": "ASSESSMENT_COMPLETED",
"session_id": "sess_9f2e1c3d",
"ats_candidate_id": "ATS-78432",
"completed_at": "2025-10-02T09:48:00+00:00",
"report_url": "https://assessment.provider.example/reports/sess_9f2e1c3d",
"composite_score": 74.2,
"recommendation": "ADVANCE"
}
PATCH /ats/v2/candidates/{ats_candidate_id}/attributes, de score terugschrijven naar je ATS
PATCH /ats/v2/candidates/ATS-78432/attributes HTTP/1.1
Host: jouw-ats.example
Authorization: Bearer {ats_access_token}
Content-Type: application/json
{
"assessment_session_id": "sess_9f2e1c3d",
"assessment_version": "3.2.1",
"scoring_model_version": "sm_2025.2",
"composite_score": 74.2,
"composite_percentile": 76,
"recommendation": "ADVANCE",
"score_synced_at": "2025-10-02T10:01:00+00:00"
}
Idempotency-Key op elke POST /invitations en POST /sessions. De sleutel moet uniek zijn per combinatie van kandidaat en assessment, bijvoorbeeld inv_{ats_candidate_id}_{assessment_id}_{datum}.event_id plus session_id. Bewaar verwerkte event_id-waarden minstens 72 uur.completed_at verpest je funnelanalyse, vooral de doorlooptijd naar de volgende stap.Voordat je één testcase draait, controleer je of je het volgende hebt.
Test je cutover nooit op productiedata. Zet historische scores pas in je productie-ATS als de stagingrun alle verificatiestappen heeft doorstaan.
Draai deze zeven tests in volgorde. Elke test moet slagen voordat je aan de volgende begint.
ats_candidate_id correct oplost en of scorevelden vullen zonder bestaande data te overschrijven200 OK teruggeeftTC-01, standaardflow. Trigger, nodig een testkandidaat uit vanuit het ATS. Verwacht, de kandidaat ontvangt de uitnodiging, rondt het assessment af en je ATS-endpoint ontvangt binnen 60 seconden een ASSESSMENT_COMPLETED-event. Het kandidaatdossier wordt bijgewerkt met composite_score, recommendation en report_url. Geslaagd als alle drie de velden gevuld zijn en er geen dubbele sessie is ontstaan.
TC-02, idempotente heruitnodiging. Trigger, stuur dezelfde POST /invitations twee keer met identieke Idempotency-Key. Verwacht, de leverancier geeft beide keren dezelfde session_id terug en er bestaat één sessie. Geslaagd als het tweede verzoek 200 of 409 met het oorspronkelijke sessieobject teruggeeft.
TC-03, historische import met versielabels. Trigger, importeer vijftig historische sessies, elk gelabeld met assessment_version en scoring_model_version. Verwacht, alle vijftig records koppelen aan bestaande kandidaatdossiers, scorevelden vullen correct en de versielabels zijn zichtbaar in je rapportagefilters. Geslaagd als er geen enkel onopgelost ats_candidate_id is en geen scoreveld leeg blijft waar de bron wel een waarde had.
TC-04, meertalige afname. Trigger, nodig een testkandidaat uit met locale: nl-NL en rond het assessment af. Verwacht, de rapportage komt terug met locale: nl-NL, de inhoud is Nederlands en je ATS ontvangt een report_language dat overeenkomt. Geslaagd als de rapporttaal klopt en er niet stilzwijgend wordt teruggevallen op Engels.
TC-05, toestemming en bewaartermijn. Trigger, maak een uitnodiging aan voor een kandidaat met een specifieke toestemmingsversie, rond het assessment af en vraag het rapport op. Verwacht, de toestemming staat in het auditlog met consent_version, consent_given_at en data_retention_expires_at. Geslaagd als alle drie de velden zowel in het auditlog van het platform als in het ATS-dossier staan.
Draai na de eerste 48 uur in productie deze controles op de logs van beide leveranciers, voor de groep kandidaten die in beide systemen voorkomt.
COMPLETED. Het totaal op het nieuwe platform moet binnen 2% liggen van wat je op basis van het uitnodigingsvolume verwachtcomposite_score. Die hoort niet meer dan 0,5 standaarddeviatie te verschuiven ten opzichte van de nulmeting van 14 dagen. Een grotere verschuiving wijst eerder op een verkeerde scoringsmodelversie dan op andere kandidatenreport_url. Trek een steekproef van vijftig rapport-URL's en controleer of ze allemaal openen met geldige credentialsZakt het afrondingspercentage verder dan afgesproken, kijk naar de tabel met KPI-grenzen hierboven, dan rol je direct terug. Terugrollen betekent dat je de uitnodigingstrigger in je ATS weer naar de oude leverancier wijst, niet alleen dat je stopt met nieuwe uitnodigingen. Wijs vooraf een eigenaar aan die de eerste 72 uur bereikbaar is.
Kandidaat-ID's die niet matchen. Koppelen op e-mailadres gaat mis zodra een kandidaat tussen sollicitatie en import van mailadres wisselt. Koppel altijd op ats_candidate_id. Heeft je huidige leverancier dat veld nooit opgeslagen, bouw dan een reconciliatiequery op e-mailadres plus uitnodigingstijdstip met een tolerantievenster, en controleer handmatig elk geval waarin twee kandidaten hetzelfde adres delen.
Stille schemawijzigingen. Leveranciers passen veldnamen en enum-waarden aan zonder dat aan te kondigen. Een veld dat eerst status: "complete" was, wordt na een kleine versiestap status: "COMPLETED". Valideer alle binnenkomende webhookpayloads en uitgaande API-responses tegen een JSON Schema. Laat het hard falen bij een onverwachte waarde in plaats van velden stilletjes te laten wegvallen.
Dubbele score-updates. Zonder idempotente webhookafhandeling schrijft een retry van een ASSESSMENT_COMPLETED-event een tweede scorerecord weg, en dan weet niemand meer welke telt. Bewaar verwerkte event_id-waarden en weiger duplicaten vóór elke schrijfactie.
Verkeerde OAuth-scopes tijdens de cutover. Een client die is ingericht met assessments:write in plaats van assessments:read slaagt in je tests en faalt in productie op het moment dat er een leesactie wordt verwacht. Documenteer per integratiepatroon welke scopes nodig zijn en test in staging bewust met verkeerde scopes.
Klokverschil en tijdzones. Een leverancier die tijdstempels in lokale tijd teruggeeft zonder offset laat je funnelanalyse uren afwijken. Dwing ISO-8601 met expliciete UTC-offset af op alle velden en bouw een validatiestap die elke tijdstempel zonder tijdzone afkeurt of markeert.
Toestemming die op een ander moment komt. Bij een overstap verandert de toestemmingsflow die kandidaten te zien krijgen. Vraagt de nieuwe leverancier toestemming op een ander punt in de journey dan de oude, dan krijgt de kandidaat een onverwacht scherm en haakt een deel af. Teken de volgorde uit en test hem end-to-end in TC-05. Selection Lab vraagt toestemming voordat resultaten worden getoond en opnieuw voordat ze worden gedeeld, wat een bruikbaar model is voor waar je toestemmingsmomenten legt.
Historie importeren zonder versielabels. Doe je dat, dan mengt je rapportage scoreverdelingen van kandidaten die onder verschillende normgroepen zijn beoordeeld. Label elk geïmporteerd record met de drie versievelden uit het schema hierboven.
Gebroken deeplinks vanuit je ATS. Staat er in kandidaatdossiers een directe URL naar een assessmentsessie, dan werken die links na de overstap niet meer. Inventariseer vóór go-live alle ATS-velden waar zulke URL's in staan en vervang of redirect ze als onderdeel van de cutover, niet erna.
Rapportages die niet meer vergelijkbaar zijn. Je nieuwe leverancier gebruikt mogelijk andere eventnamen of berekent uitval in een andere funnelfase. Map de oude eventnamen expliciet op de nieuwe voordat je de koppeling afrondt, en controleer of je dashboards dezelfde KPI's opleveren. Een daling in uitval betekent alleen iets als je die uitval voor en na de overstap op dezelfde manier berekent.
Loopt er iets mis tijdens of na de cutover, volg dan deze route.
session_id, event_id en request_id erbijats_candidate_id, session_id en event_idWijs vóór de cutover iemand aan die mag beslissen om terug te rollen, zonder dat daar nog goedkeuring bij hoeft. Houd op de dag zelf het volgende continu open.
Zet dit in je exportverzoek aan de vertrekkende leverancier.
COMPLETED-sessies of alle sessiesVan assessmentleverancier wisselen zonder je hiring pipeline te verstoren is een uitvoeringsvraagstuk, geen strategievraagstuk. De patronen hierboven geven je een concreet QA-kader om te controleren of elke stap in de funnel werkt voordat je definitief overgaat. Draai de testcases, bewaak je KPI-grenzen en houd de eigenaar van het terugrolbesluit bereikbaar.
Reken op 2 tot 10 weken van eerste exportaanvraag tot go-live, afhankelijk van hoeveel historie je meeneemt en hoe diep de ATS-koppeling gaat. De export bij je vertrekkende leverancier is meestal de traagste stap, dus vraag die doorlooptijd schriftelijk op voordat je een cutoverdatum vastlegt.
Ruwe kandidaat- en sessiedata valt onder artikel 20 AVG en is in principe overdraagbaar. Scores en aanbevelingen die het platform zelf heeft berekend, kunnen daarbuiten vallen omdat ze het oordeel van de verwerkingsverantwoordelijke zijn. Laat je functionaris gegevensbescherming per veld bepalen wat overdraagbaar is en wat je opnieuw moet genereren.
Vier dingen. Kandidaten koppelen op e-mailadres in plaats van op het kandidaat-ID uit je ATS, historie importeren zonder versielabels, webhooks die niet dedupliceren en gebroken deeplinks in bestaande kandidaatdossiers. Alle vier zijn stille fouten, dus je ziet ze pas terug in je rapportage.
Spreek het getal vooraf af. Een gangbare grens is een daling van het afrondingspercentage met meer dan 5 procentpunt ten opzichte van de nulmeting van 14 dagen, of een slagingspercentage van webhookleveringen onder 98%. Terugrollen betekent dat je de uitnodigingstrigger in je ATS weer naar de oude leverancier wijst.
Niet als je de toestemmingsflow en de uitnodigingsmail meetest voordat je live gaat. De meeste uitval bij een overstap komt niet van het assessment zelf, maar van een onverwacht toestemmingsscherm of een deeplink die niet meer werkt. Test beide in staging via TC-05.