ABN Data Model
Opmerking toevoegen
Je kunt opmerkingen plaatsen via Opmerking toevoegen aan de rechterkant van de pagina.
Over dit document
Dit document legt uit hoe we vacaturegegevens opslaan en wat elk veld betekent. We schrijven het in heldere taal, oftewel Algemeen Beschaafd Nederlands, zodat iedereen het kan volgen, of je nu in de backoffice werkt, kandidaten matcht, of gewoon wilt snappen hoe het systeem in elkaar zit.
Waarom hebben we een datamodel nodig?
Vacatures komen uit verschillende bronnen: STRIIVE, Flextender, Yacht, Maandag en andere DAS-platformen. Elk platform gebruikt eigen termen. De een noemt het "tarief", de ander "salaris" of "rate". Het ene systeem geeft uren per week, het andere per dag.
Dat levert verwarring op. Als je vacatures wilt vergelijken, filteren of publiceren, moet je eerst weten wat er staat en hoe het bedoeld is.
Ons datamodel lost dit op. Het is een afspraak: ongeacht waar een vacature vandaan komt, we slaan hem altijd op dezelfde manier op. Vaste veldnamen, vaste formaten, vaste betekenissen.
Praktisch voorbeeld:
| Bron | Wat zij zeggen | Wat wij opslaan |
|---|---|---|
| STRIIVE | "rate" | contract_min_rate_eur |
| Flextender | "tarief per uur" | contract_min_rate_eur |
| Yacht | "salaris" | contract_min_rate_eur |
Het resultaat: alle vacatures zien er hetzelfde uit, ongeacht de bron.
Wie gebruikt dit waarvoor?
Het datamodel is niet alleen voor technici. Het bepaalt wat iedereen ziet en kan doen:
Backoffice gebruikt het om vacatures te controleren voordat ze online gaan. Klopt het tarief? Is de sluitingsdatum ingevuld? Past de opdrachtgever bij de standplaats?
Frontoffice gebruikt het om kandidaten te matchen en vragen te beantwoorden. Als een kandidaat vraagt "hoeveel uur per week?", moet dat veld kloppen.
Kandidaten zien uiteindelijk wat er gepubliceerd is. Fouten in de data worden fouten op de website.
Daarom is elk veld belangrijk, niet alleen technisch maar ook operationeel.
Hoe is het datamodel opgebouwd?
We werken met drie lagen:
- Kern van de vacature: titel, status, datums, inhoud, tarieven, uren, indieningsvereisten en AVG-beperkingen.
- Relaties: opdrachtgever (met type en regio), standplaats, contactpersoon, rollen, thema's, contractvormen.
- Publicatie en bewijs: documenten, snapshots, broninformatie, integraties.
Hieronder leggen we elke laag stap voor stap uit.
De vacature zelf
Elke vacature heeft een kern: de basisgegevens die je nodig hebt om te weten wat het is en wanneer het speelt.
Titel en status
De titel is simpelweg de functienaam. "Senior Java Developer", "Projectleider Digitalisering", dat soort dingen. Dit is wat kandidaten als eerste zien.
De status vertelt waar de vacature staat in het proces:
| Status | Wat betekent dit? |
|---|---|
| draft | Net opgehaald, nog niet gepubliceerd |
| published | Live op de website, kandidaten kunnen reageren |
| closed | Deadline is verstreken, geen nieuwe reacties meer |
| archived | Klaar, opgeslagen voor administratie |
Technische velden: job.job_title, job.job_status
Datums
Een vacature heeft meerdere datums. Dit zijn de belangrijkste:
| Datum | Wat is dit? | Voorbeeld |
|---|---|---|
| Sluitingsdatum | Tot wanneer kunnen kandidaten reageren? | 15-02-2026 14:00 |
| Startdatum | Wanneer begint de opdracht? | 01-03-2026 |
| Einddatum | Wanneer is de opdracht klaar? | 01-09-2026 |
| Gepubliceerd op | Wanneer hebben we hem online gezet? | 22-01-2026 11:00 |
Als de sluitingsdatum ontbreekt of in het verleden ligt, kan de vacature niet gepubliceerd worden. Dat is een harde regel.
Technische velden: job.job_closure_datetime, job.job_start_datetime, job.job_end_datetime, job.job_published_at
Omschrijving en eisen
De omschrijving is de volledige tekst van de opdracht, vaak in HTML-formaat zodat we opmaak kunnen behouden.
De eisen zijn wat de opdrachtgever vraagt: opleidingsniveau, jaren ervaring, certificaten, VOG.
De selectiecriteria leggen uit hoe de opdrachtgever kiest: "Prijs 40%, Kwaliteit 60%" of "Laagste prijs wint".
Voorbeeld:
- Eisen: HBO, minimaal 5 jaar ervaring, VOG vereist
- Selectiecriteria: Prijs 40%, Kwaliteit 60%
Technische velden: job.job_description_html, job.job_requirements, job.job_selection_criteria
Geld en tijd
Tarief
Het tarief is wat de kandidaat per uur verdient. We slaan dit op als een bandbreedte: een minimum en een maximum.
| Veld | Wat is dit? | Voorbeeld |
|---|---|---|
| Minimum tarief | Het laagste uurtarief | 80 EUR |
| Maximum tarief | Het hoogste uurtarief | 100 EUR |
Let op: Het minimum mag nooit hoger zijn dan het maximum. Als dat wel zo is, klopt er iets niet en moet je de bron checken.
Tarieven zijn altijd in euro's per uur. Als de bron dagtarieven geeft, rekenen we die om.
Als een bron geen uurtarief geeft maar een maandrange, rekenen we die alleen terug naar een indicatief minimum- en maximumuurtarief als het aantal uren per week bekend is. Ontbreekt die context, dan blijft de maandrange broninformatie en markeren we de vacature voor handmatige controle.
Technische velden: job.contract_min_rate_eur, job.contract_max_rate_eur
Uren per week
Hoeveel uur per week werkt de kandidaat? Ook dit slaan we op als bandbreedte.
| Veld | Wat is dit? | Voorbeeld |
|---|---|---|
| Minimum uren | Het minste dat je moet werken | 32 uur/week |
| Maximum uren | Het meeste dat je kunt werken | 40 uur/week |
Realistische waarden liggen tussen 8 en 40 uur per week. Alles daarbuiten is verdacht.
Technische velden: job.contract_min_hours_per_week, job.contract_max_hours_per_week
Duur en verlenging
Hoe lang duurt de opdracht? En kan die verlengd worden?
| Veld | Wat is dit? | Voorbeeld |
|---|---|---|
| Duur | Hoe lang duurt het contract? | 6 maanden |
| Verlenging mogelijk? | Kan het verlengd worden? | Ja |
| Aantal verlengingen | Hoeveel keer? | 2 keer |
| Verlenging per keer | Hoeveel maanden per verlenging? | 3 maanden |
Voorbeeld: "6 maanden, optie tot 2x 3 maanden verlenging"
Dit betekent: het contract duurt eerst 6 maanden, en daarna kan het twee keer met 3 maanden verlengd worden.
De verlenging slaan we op als een object met drie onderdelen:
- Status:
yes,no,possible, ofonbekend - Aantal: hoeveel keer verlengen
- Maanden: hoeveel maanden per verlenging
Technische velden: job.contract_duration_months, job.contract_extension
Indieningsvereisten
Bij veel aanbestedingen gelden regels over hoe een kandidaat zich mag aanbieden. Die regels komen uit het DAS-platform en slaan we mee op.
| Veld | Wat is dit? | Voorbeeld |
|---|---|---|
| Motivatie vereist? | Moet de kandidaat een motivatie schrijven? | Ja |
| Maximaal aantal kandidaten | Hoeveel kandidaten mogen we aanbieden? | 3 |
| Toegestane bestandstypen | Welke bestanden mag je uploaden? | PDF, DOCX |
| Maximaal aantal CV-pagina's | Hoe lang mag het CV zijn? | 5 pagina's |
| Maximaal aantal tekens motivatie | Hoe lang mag de motivatie zijn? | 2000 tekens |
Dit is belangrijk voor frontoffice bij het voorbereiden van een aanbieding. Als je meer pagina's of kandidaten aanbiedt dan toegestaan, wordt de inschrijving afgekeurd.
Technische velden: job.contract_submission_requirements
DAS-vereisten
Sommige DAS-platformen stellen aanvullende eisen aan leveranciers. Denk aan verplichte certificeringen, registratie bij het platform, of een specifiek kwaliteitskeurmerk.
We slaan deze eisen mee op zodat backoffice kan controleren of we aan de voorwaarden voldoen voordat we een kandidaat aanbieden.
Technische velden: job.contract_das_requirements
AVG-beperkingen
Bij bepaalde opdrachten gelden privacyregels voor wat je wel en niet mag delen over een kandidaat. Voorbeelden:
- Geen pasfoto meesturen
- Geen woonadres vermelden
- Geheimhoudingsverklaring vereist
- VOG (Verklaring Omtrent het Gedrag) vereist
Als deze beperkingen zijn ingevuld, moet frontoffice hier rekening mee houden bij het opstellen van de aanbieding. Het systeem kan hier ook automatisch op controleren.
Technische velden: job.contract_gdpr_requirements
Wie en waar
Opdrachtgever
De opdrachtgever is de organisatie die de opdracht uitschrijft. Dit kan een gemeente zijn, een waterschap, een ministerie, of een andere publieke instelling.
We slaan het volgende op:
| Veld | Wat is dit? | Voorbeeld |
|---|---|---|
| Naam | De naam van de organisatie | Gemeente Utrecht |
| Adres | Straat, nummer, postcode, plaats | Stadhuisplein 1, 3511 AA Utrecht |
| Type | Wat voor soort organisatie? | Gemeente |
| Regio | In welke provincie? | Utrecht |
| Website | De website van de organisatie | utrecht.nl |
Zonder opdrachtgever kan een vacature niet gevalideerd worden. Dit is een verplicht veld.
Organisatietypes:
| Type | Sector |
|---|---|
| Gemeente | Publiek |
| Provincie | Publiek |
| Waterschap | Publiek |
| Ministerie | Publiek |
| Rijksoverheid | Publiek |
| Semi-overheid | Publiek |
| Zorginstelling | Non-profit |
| Onderwijsinstelling | Non-profit |
| Overig | Anders |
Regio's (provincies):
| Drenthe | Flevoland | Friesland | Gelderland |
| Groningen | Limburg | Noord-Brabant | Noord-Holland |
| Overijssel | Utrecht | Zeeland | Zuid-Holland |
Technische velden: headquarters (met alle adresvelden), org_type, region
Standplaats
De standplaats is waar de kandidaat daadwerkelijk gaat werken. Dit kan anders zijn dan het hoofdkantoor van de opdrachtgever.
Voorbeeld: De opdrachtgever is Rijkswaterstaat in Den Haag, maar de standplaats is een projectlocatie in Groningen.
Technische velden: work_location
Contactpersoon
Als er een aanspreekpunt is voor vragen over de opdracht, slaan we die hier op.
| Veld | Wat is dit? | Voorbeeld |
|---|---|---|
| Naam | Voor- en achternaam | Jan Jansen |
| E-mailadres | jan.jansen@gemeente.nl | |
| Telefoon | Telefoonnummer | 030-286 0000 |
Technische velden: contact
Categorisering
Rollen
Een rol beschrijft wat voor functie het is. Een vacature kan meerdere rollen hebben.
| Rol | Wat betekent dit? |
|---|---|
| Developer | Software ontwikkelaar |
| Architect | Technisch architect |
| Project Manager | Projectleider |
| Business Analyst | Business analist |
| Tech Lead | Technisch leider |
| Scrum Master | Scrum master |
| Product Owner | Product owner |
Voorbeeld: Een vacature "Technisch Projectleider" kan zowel de rol "Project Manager" als "Tech Lead" hebben.
Technische velden: job_role, role
Thema's
Thema's beschrijven waar de opdracht over gaat. Ook hier kan een vacature meerdere thema's hebben.
| Thema | Wat betekent dit? |
|---|---|
| Agile & Scrum | Agile werkwijzen, scrum implementaties |
| Digitalisering | Digitale transformatie projecten |
| Cloud & Infrastructure | Cloud migraties, infrastructuur |
| Security | Beveiliging, informatiebeveiliging |
| Data & Analytics | Data projecten, analytics, BI |
| DevOps | DevOps praktijken, CI/CD |
| Datagedreven werken | Data-driven besluitvorming |
Voorbeeld: Een vacature "Data Engineer voor Digitale Transformatie" kan de thema's "Digitalisering" en "Data & Analytics" hebben.
Technische velden: job_theme, theme
Contractvormen
Hoe kan de kandidaat ingehuurd worden? Dit bepaalt hoe de facturatie en contractering verloopt.
| Type | Wat betekent dit? |
|---|---|
| ZZP | Zelfstandige zonder personeel, freelance |
| ZZP - Eenmanszaak | ZZP via een eenmanszaak |
| ZZP - VOF | ZZP via een VOF |
| ZZP - BV | ZZP via een BV |
| Detachering | Via payroll/detacheringsbureau |
| Detachering - DPP | Via DPP payroll |
| Detachering - Extern | Via een andere organisatie |
| Detachering - Kickback | DPP met kickback fee |
| Doorleen | Doorleen constructie |
| Beide | ZZP en Detachering beide mogelijk |
| Onbekend | Niet gespecificeerd |
Een vacature kan meerdere contractvormen toestaan. Bijvoorbeeld: "ZZP of Detachering".
Technische velden: job_contract_type, contract_type
Sector en opleidingsniveau
Voor filtering gebruiken we ook sector en opleidingsniveau.
Sectoren:
| Sector |
|---|
| Beleid en Bestuurlijke zaken |
| Communicatie en Voorlichting |
| Financiën en Economische zaken |
| ICT en Automatisering |
| Juridisch |
| HR en Personeel |
Opleidingsniveaus:
| Niveau | Betekenis |
|---|---|
| vmbo | VMBO |
| mbo | MBO |
| hbo | HBO |
| wo | WO |
| onbekend | Niet gespecificeerd |
Technische velden: job.sector_id, job.education_level
Herkomst en traceerbaarheid
Platform
Elke vacature komt van een DAS-platform. We houden bij welk platform dat is en wat het originele ID was.
| Platform | Website |
|---|---|
| STRIIVE | striive.com |
| Flextender | flextender.nl |
| Yacht | yacht.nl |
| Maandag | maandag.com |
| Headfirst | headfirst.nl |
| Inhuurdesk | inhuurdesk.nl |
| POOLZ | poolz.nl |
| Magnit | magnit.com |
| Circle8 | circle8.eu |
| Mercell | mercell.com |
| Salesforce | salesforce.com |
| TSF | tsf.nl |
Technische velden: platform, platform_id, job.platform_job_id
Bronverwijzing
Om altijd terug te kunnen naar de originele vacature, slaan we de bron-URL op. Dit is de link naar de pagina waar we de vacature vandaan gehaald hebben.
Technische velden: job.job_source_url
DPP referentie
We geven elke vacature ook een eigen referentienummer. Dit is ons interne nummer, los van wat het platform gebruikt.
Voorbeeld: DPP-2026-001234
Technische velden: job.job_dpp_reference_id
Documenten
Vaak zitten er bijlagen bij een vacature: het aanbestedingsdocument (tender PDF), aanvullende eisen, algemene voorwaarden.
| Document type | Wat is dit? |
|---|---|
| source_html | De originele webpagina |
| tender_pdf | Het aanbestedingsdocument |
| annex | Bijlagen met aanvullende eisen |
| terms | Algemene voorwaarden |
| other | Overige documenten |
We slaan de documenten op en halen er waar mogelijk tekst uit, zodat we kunnen zoeken in de inhoud.
Technische velden: job_document
Publicatie
Waar staat de vacature online?
Als een vacature gepubliceerd is, slaan we op waar die te vinden is:
| Kanaal | Wat slaan we op? | Voorbeeld |
|---|---|---|
| Website | WordPress post ID | 5678 |
| Nieuwsbrief | Nieuwsbrief selectie | nl_ict_weekly |
Technische velden: job_posting, integration_frontend, newsletter_job
Koppelingen met andere systemen
De vacaturedata gaat niet alleen naar de website. We koppelen ook met:
WordPress (depubliekepartner.nl)
- Vacatures worden automatisch gepubliceerd
- We slaan de post ID en URL op
VBout (nieuwsbrieven)
- Geselecteerde vacatures gaan naar de nieuwsbrief
- We houden bij in welke nieuwsbrief een vacature is opgenomen
TESS (kandidaat matching)
- Alle vacaturedata gaat naar TESS
- TESS matcht kandidaten, genereert voorstellen, en regelt inschrijving
Relaties (visueel)
erDiagram
PLATFORM ||--o{ JOB : bron
JOB ||--|| HEADQUARTERS : opdrachtgever
JOB ||--|| WORK_LOCATION : standplaats
JOB ||--o{ JOB_ROLE : heeft
ROLE ||--o{ JOB_ROLE : tag
JOB ||--o{ JOB_THEME : heeft
THEME ||--o{ JOB_THEME : tag
JOB ||--o{ JOB_CONTRACT_TYPE : optie
CONTRACT_TYPE ||--o{ JOB_CONTRACT_TYPE : typeHoe data van bron naar publicatie stroomt
Een vacature maakt een reis van het DAS-platform naar de website. Dat gaat zo:
flowchart LR A[DAS-platform] --> B[Scraper haalt op] B --> C[Vertaling naar ons model] C --> D[Opslag in database] D --> E[Controle door backoffice] E --> F[Publicatie op website]
Stap 1: Ophalen De scraper haalt de vacature op van het DAS-platform. Dit kan een API-koppeling zijn of het uitlezen van een webpagina.
Stap 2: Vertalen
We zetten alle velden om naar ons datamodel. "Rate" wordt contract_min_rate_eur, "tarief per uur" ook.
Stap 3: Opslaan De vacature gaat de database in met status "draft".
Stap 4: Controleren Backoffice checkt of alles klopt: tarief, uren, opdrachtgever, datums.
Stap 5: Publiceren Als alles goed is, wordt de status "published" en verschijnt de vacature op de website.
Status veranderingen
Een vacature doorloopt deze statussen:
draft → published → closed → archived| Van | Naar | Wanneer? |
|---|---|---|
| draft | published | Na controle door backoffice |
| published | closed | Als de sluitingsdatum verstreken is |
| closed | archived | Na afronding van het selectieproces |
Checklist voor data review
Als je een vacature controleert, check dan het volgende:
Verplichte velden
| Wat | Check | Technisch veld |
|---|---|---|
| Titel | Is ingevuld? | job.job_title |
| Platform | Is gekoppeld? | platform_id |
| Origineel ID | Is ingevuld? | job.platform_job_id |
| Opdrachtgever | Is gekoppeld? | headquarters |
Belangrijke controles
| Wat | Vraag jezelf af | Realistische waarden |
|---|---|---|
| Tarief | Min lager dan max? | 50 - 200 EUR/uur |
| Uren | Min lager dan max? | 8 - 40 uur/week |
| Sluitingsdatum | Ligt in de toekomst? | - |
| Startdatum | Na sluitingsdatum? | - |
| Einddatum | Na startdatum? | - |
| Opdrachtgever | Correct gekoppeld? | - |
| Regio | Past bij standplaats? | - |
| Contractvorm | Minimaal 1 gekozen? | - |
| Indieningsvereisten | Aantal kandidaten en bestandstypen kloppen? | - |
| AVG-beperkingen | Zijn er privacyregels om rekening mee te houden? | - |
Veelvoorkomende problemen
| Probleem | Hoe los je dit op? |
|---|---|
| Tarief ontbreekt | Check de bron, vul handmatig in als het er staat |
| Verkeerde opdrachtgever | Zoek de juiste op en koppel opnieuw |
| Geen contractvorm | Selecteer minimaal "Onbekend" |
| Datum in verleden | Check of de vacature nog actief is op de bron |
| Dubbele vacature | Controleer platform_job_id, mogelijk al aanwezig |
| Te veel kandidaten aangeboden | Check contract_submission_requirements, maximaal aantal staat daar |
| Pasfoto meegestuurd terwijl dat niet mag | Check contract_gdpr_requirements voor AVG-beperkingen |
Tips
- Klik altijd door naar de bron-URL - Vergelijk wat er in ons systeem staat met het origineel
- Let op tarieven - Sommige bronnen geven dagtarieven in plaats van uurtarieven
- Check verlengingen - Die staan vaak in de PDF bijlagen, niet in de hoofdtekst
- Regio vs standplaats - De standplaats kan in een andere regio liggen dan het hoofdkantoor
- Check indieningsvereisten - Maximaal aantal CV-pagina's en kandidaten verschilt per aanbesteding
- AVG altijd controleren - Als er beperkingen staan, gelden die voor elke aanbieding op die vacature
Samenvatting
| Onderwerp | Kern |
|---|---|
| Rollen | Een vacature kan meerdere rollen hebben |
| Thema's | Een vacature kan meerdere thema's hebben |
| Contractvormen | 11 types, van ZZP tot Detachering |
| Tarieven | Altijd in euro per uur, als bandbreedte |
| Uren | Altijd per week, als bandbreedte |
| Opdrachtgever | Verplicht, met volledig adres, type en regio |
| Indieningsvereisten | Regels per aanbesteding: aantal kandidaten, bestanden, paginalimiet |
| AVG-beperkingen | Privacyregels over wat je wel en niet mag delen |
| Platformen | 12 actieve DAS-bronnen |
| Bron | Altijd traceerbaar via platform en URL |
Feedback geven
Zie je iets dat niet klopt? Gebruik de technische veldnaam in je opmerking. Dat scheelt zoeken.
Voorbeeld: "Het veld contract_max_rate_eur lijkt te hoog, 500 EUR/uur is onrealistisch voor deze functie."
Een korte zin met het veld en het probleem is genoeg.