Ga naar de inhoud

Documentatie

SIA Intelligence API

Eén endpoint. Je stuurt een casus, je krijgt dezelfde analyse terug die het portaal op het scherm zet, als JSON, met de bronnen en hun status erbij. De casus staat ook in het portaal, met de analyse en het audittrail.

Authenticatie

Elke aanroep draagt een sleutel in de Authorization-header: Bearer sia_… . De sleutel bepaalt om welke werkruimte het gaat; er wordt geen sessiecookie geaccepteerd, ook niet als je in dezelfde browser bent ingelogd. Een onbekende of ingetrokken sleutel geeft 401 met code invalid_key.

Sleutels beheer je in Instellingen → API, op het pakket SIA Organisation. Een sleutel wordt één keer getoond en daarna alleen nog als voorvoegsel; intrekken werkt direct. Pakketten bekijken

Endpoints

  • POST/api/v1/intelligence

    Analyseert een casus. Telt als 5 eenheden verbruik. De casus wordt in je werkruimte geopend zoals een casus op het scherm, met de eigenaar van de sleutel als eigenaar (standaard wie de sleutel heeft gemaakt), en geanalyseerd met dezelfde pipeline als het portaal, met het geheugen van je organisatie. Hij staat onder Casussen en het Dossier vermeldt "via API-sleutel <naam>". Elke aanroep, ook elke leesactie, staat in het audittrail van de casus.

  • GET/api/v1/intelligence/{case_id}

    Geeft een eerder opgeslagen analyse terug, voor de werkruimte van de sleutel. Kost niets.

Beide antwoorden dragen Cache-Control: no-store. Bewaar ze aan jouw kant zoals je een personeelsdossier bewaart.

Dezelfde API als machineleesbare beschrijving, voor je eigen tooling of een HRIS-koppeling:OpenAPI 3.1 (openapi.json)

Wat je stuurt

Eén JSON-object. Alles wat je meegeeft wordt onderdeel van de casus; alles samen is maximaal 4.000 tekens.

VeldTypeVerplichtOmschrijving
case_datestring (YYYY-MM-DD)JaDe datum waarop de regels gelezen moeten worden. Niet in de toekomst, niet vóór 2000-01-01.
descriptionstringJaDe casus in gewone taal. Tussen 20 en 4.000 tekens.
language"nl" | "en"JaDe taal van het antwoord.
absence_dayintegerNeeDe hoeveelste verzuimdag het is, geteld vanaf de eerste ziektedag.
previous_interventionsstring[]NeeWat er al is geprobeerd. Maximaal tien regels van elk 300 tekens.
manager_contextstringNeeWat de leidinggevende zegt of wil. Maximaal 1.000 tekens.
occupational_health_statusstringNeeDe stand van zaken bij de bedrijfsarts. Maximaal 500 tekens.
referencestringNeeJe eigen kenmerk voor de casus. Wordt de referentie van het dossier; zonder kenmerk genereert SIA er een.
employee_rolestringNeeDe functie van de werknemer, bijvoorbeeld "magazijnmedewerker". Nooit een naam. Maximaal 80 tekens.
first_sick_daystring (YYYY-MM-DD)NeeDe eerste ziektedag, op of voor case_date. Met deze datum berekent SIA zelf de poortwachtertermijnen, geeft ze terug als timeline en neemt de volgende deadline daaruit over.
eventsobject[]NeeWat er sinds de eerste ziektedag is gebeurd: { kind, date, sanction_weeks }. kind is full_recovery, relapse, partial_recovery, second_track, deskundigenoordeel of loonsanctie; sanction_weeks (1 tot 52) alleen bij een loonsanctie. Alleen samen met first_sick_day, maximaal twintig.
confirm_free_textbooleanNeeSIA controleert vrije tekst op termen die lijken op een diagnose, medische details, een leeftijd, een geslacht of details over derden. Bij een treffer volgt 422 free_text_confirmation met de treffers per veld. Haal ze weg, of stuur hetzelfde verzoek opnieuw met true als de tekst klopt.
triageobjectNeeDe triagekaart uit het portaal: { factors, boundary, next_step_owner, signals }. factors uit medical (alleen het proces), conflict, workload, performance, organisational, personal, unclear; boundary uit self, company_doctor, labour_expert, legal, mediation, sia_human; next_step_owner is case_manager, manager, hr of external. Wordt bij de casus bewaard en door de analyse gelezen. Met boundary sia_human en geen andere factor dan unclear gaat de casus direct naar een expert: er draait geen analyse en er wordt niets geteld. Je krijgt 202 met status awaiting_confirmation en de aanbeveling van SIA (expert_recommendation). Er wordt via de API geen expertticket geopend: de eigenaar van de casus bevestigt de expertbeoordeling in SIA via confirm_url.
departmentstringNeeDe afdeling, zoals op het casusformulier. Hooguit 120 tekens.
absence_type"full" | "partial"NeeVolledig of gedeeltelijk verzuim.
client_employer_iduuidNeeDe klantwerkgever waarvoor de casus is, uit je eigen werkruimte. SIA gebruikt dan het geheugen en profiel van die klant naast dat van de werkruimte, en van geen andere klant.

Wat je terugkrijgt

Dezelfde velden als elk antwoord en elke analyse in het portaal, de spine.

VeldTypeOmschrijving
case_iduuidHet dossier. Hiermee haal je de analyse later weer op.
categorystringanswer, insufficient_information, expert_judgement_required of refused.
assessmentstringWat hier volgens SIA werkelijk aan de hand is.
reasoningstringDe juridische en procedurele redenering, met verwijzingen [1] naar de bronnen hieronder.
actionstringDe volgende stap: wat, door wie, wanneer.
deadlineobject | null{ date, label, days_from_case_date }, of null als er geen volgende datum is. Het aantal dagen wordt door SIA berekend en is null als er geen datum staat. Met first_sick_day komt de datum uit de berekende tijdlijn, niet van het model.
riskstringWat er misgaat als de actie uitblijft.
sourcesarray{ title, version, article, status } per bron. Alleen bronnen die daadwerkelijk zijn gebruikt en gecontroleerd.
confidence"low" | "medium" | "high"Hoe zeker SIA van deze analyse is.
escalationobject{ required, reason, to }. to is expert_review of null. Bij required: true hoort deze casus ook bij een mens.
missing_informationstring[]De één tot drie vragen die SIA beantwoord wil zien voordat het verdergaat. Leeg als die er niet zijn.
ai_generatedtrueAltijd true: de blokken in ai_blocks zijn geschreven door SIA, een AI-systeem (AI-verordening art. 50). Toon ze in je eigen systeem als AI-uitvoer.
ai_noticestringEen korte AI-melding in de taal van het antwoord, om naast de blokken te tonen.
ai_blocksstring[]De velden die SIA heeft geschreven: category, assessment, reasoning, action, deadline, risk, confidence, escalation en missing_information. sources, credits en timeline zijn geen AI-tekst.
creditsobject{ charged, balance }: het verbruik van deze aanroep en wat er over is, in eenheden. Bij een GET is charged altijd 0. Het veld heet in v1 nog credits.
timelineobject[] | nullDe poortwachtertermijnen, berekend vanaf first_sick_day: { key, rule, week, due, status, basis, shiftedBy, until }. status is upcoming, due_soon, overdue of done; basis is het artikel of de paragraaf van de Werkwijzer. null als er geen first_sick_day is meegestuurd.

Een voorbeeld

Vervang sia.example.com door het adres van je eigen werkruimte.

Aanroep

curl -X POST https://sia.example.com/api/v1/intelligence \
  -H "Authorization: Bearer sia_YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{
      "case_date": "2026-09-10",
      "absence_day": 62,
      "description": "Een medewerker is op 10 juli uitgevallen na een conflict met zijn leidinggevende over de roosterindeling. Er is nog geen plan van aanpak opgesteld.",
      "previous_interventions": [
          "Gesprek met HR op 24 juli"
      ],
      "manager_context": "De leidinggevende wil een vaststellingsovereenkomst bespreken.",
      "occupational_health_status": "Spreekuur op 5 augustus; geen medische beperkingen.",
      "language": "nl",
      "reference": "WT-0447",
      "employee_role": "magazijnmedewerker"
  }'

Antwoord

{
  "case_id": "2d83f619-e968-489d-935a-362f6907de11",
  "category": "expert_judgement_required",
  "assessment": "Op verzuimdag 62 ontbreekt het plan van aanpak, terwijl het spreekuur van de bedrijfsarts op 5 augustus vermoedelijk aanleiding gaf om dit uiterlijk twee weken later op te stellen.",
  "reasoning": "De wettelijke termijn is twee weken na het oordeel van de bedrijfsarts wanneer er mogelijkheden zijn om terugkeer naar arbeid te bevorderen [3]. Omdat niet duidelijk is of op 5 augustus een formele probleemanalyse of schriftelijk oordeel is uitgebracht, is de precieze grondslag van de termijn nog te bevestigen.",
  "action": "Stel vandaag samen met de werknemer een schriftelijk plan van aanpak op en leg de afzonderlijke vraag over de vaststellingsovereenkomst ter beoordeling voor aan een SIA-expert (SIA Expert Review).",
  "deadline": {
    "date": "2026-09-10",
    "label": "Onverwijld herstellen van het ontbrekende plan van aanpak",
    "days_from_case_date": 0
  },
  "risk": "Zonder actie blijven concrete re-integratiedoelen, termijnen, evaluatieafspraken en verantwoordelijkheden ontbreken en blijft het re-integratiedossier onvolledig.",
  "sources": [
    {
      "title": "Regeling procesgang eerste en tweede ziektejaar",
      "version": "2025-07-01",
      "article": "Regeling procesgang eerste ziektejaar > Artikel 4. Het plan van aanpak",
      "status": "legal_requirement"
    },
    {
      "title": "Werkwijzer Poortwachter",
      "version": "2022-08-01",
      "article": "3.2 Onderdelen re-integratieverslag",
      "status": "official_guidance"
    }
  ],
  "confidence": "medium",
  "escalation": {
    "required": true,
    "reason": "Het bespreken en beoordelen van een vaststellingsovereenkomst vraagt om menselijke juridische beoordeling door een SIA-expert en moet gescheiden blijven van de verzuimbegeleiding.",
    "to": "expert_review"
  },
  "missing_information": [
    "Is op 5 augustus een formele probleemanalyse of een schriftelijk advies van de bedrijfsarts uitgebracht?",
    "Ligt er al een concreet voorstel voor een vaststellingsovereenkomst?"
  ],
  "ai_generated": true,
  "ai_notice": "Gegenereerd door SIA, een AI-systeem. Dit is een advies, geen besluit: een mens beoordeelt het voordat er iets gebeurt. Geen medisch of juridisch advies.",
  "ai_blocks": ["category", "assessment", "reasoning", "action", "deadline", "risk", "confidence", "escalation", "missing_information"],
  "credits": {
    "charged": 0,
    "balance": 1220
  }
}

Categorieën

Elk antwoord zegt zelf van welke soort het is, zodat je systeem er iets anders mee kan doen.

WaardeBetekenis
answerEen antwoord op de casus zoals die is voorgelegd.
insufficient_informationSIA raadt niet. De vragen die nodig zijn staan in missing_information; stuur ze beantwoord opnieuw in.
expert_judgement_requiredDe casus hoort bij een mens. escalation.to is expert_review en escalation.reason zegt waarom.
refusedBuiten de grens: medisch, privacygevoelig of formeel-juridisch. Het antwoord zegt in gewone taal waarom.

Bronstatus

Elke bron draagt haar eigen gezag. Wetgeving en officiële richtlijnen gaan vóór praktijk en oordeel als die elkaar tegenspreken, en het antwoord zegt dat dan ook.

WaardeBetekenis
legal_requirementWetgeving. Niet onderhandelbaar.
official_guidanceRichtlijnen van de overheid of UWV, zoals de Werkwijzer Poortwachter.
sia_best_practiceHet eigen materiaal van de praktijk: protocollen, sjablonen, brieven.
expert_judgementHet redeneerkader en de casusbibliotheek van de SIA-expert zelf.
licensed_sourceIngekocht of gelicentieerd materiaal.
sia_conceptEigen materiaal van de praktijk dat nog niet volledig is geverifieerd.

Verbruik en limieten

Een analyse telt als 5 eenheden verbruik, en pas als er ook echt een antwoord is: bij category insufficient_information of expert_judgement_required is charged 0 en telt er niets. Is het verbruik van je werkruimte op, dan antwoordt het endpoint 402 met code credits en wat er nog over is. Ophalen met GET telt niet mee. Het JSON-veld en de foutcode heten in v1 nog credits, zodat bestaande koppelingen blijven werken; ze gaan over hetzelfde verbruik.

Per sleutel gelden 30 analyses per tien minuten, met een eigen budget voor het ophalen. Over de limiet volgt 429 met een Retry-After-header.

Foutcodes

  • 401 missing_keyGeen Authorization-header, of geen Bearer-schema.
  • 401 invalid_keyDe sleutel is onbekend of ingetrokken.
  • 400 invalid_requestDe velden kloppen niet. errors zegt per veld wat eraan mankeert.
  • 402 creditsHet verbruik van je werkruimte is op. Het object credits geeft balance en required, in eenheden.
  • 429 rate_limitedTe veel aanroepen. Retry-After zegt hoe lang.
  • 429 spend_capJe werkruimte heeft de verwerkingslimiet van vandaag bereikt. Die gaat om middernacht (Amsterdamse tijd) weer open; Retry-After zegt hoe lang. Er is niets geanalyseerd of geteld.
  • 402 trial_expiredDe proefperiode of het abonnement van je werkruimte is afgelopen, dus de werkruimte is alleen-lezen. Nieuwe analyses wachten tot er een abonnement is; lezen blijft werken.
  • 403 workspace_deletedDeze werkruimte is verwijderd, dus de sleutels werken niet meer.
  • 404 case_not_foundGeen geanalyseerd dossier van jou met dat id.
  • 401 key_expiredDe sleutel is verlopen. Maak een nieuwe aan.
  • 403 insufficient_scopeDe sleutel mist de scope die dit endpoint vraagt.
  • 400 invalid_idempotency_keyDe Idempotency-Key is leeg, te lang of bevat ongeldige tekens.
  • 409 idempotency_in_progressEen aanroep met deze Idempotency-Key loopt nog.
  • 422 idempotency_mismatchDeze Idempotency-Key is al gebruikt met een andere body.
  • 422 free_text_confirmationVrije tekst bevat termen die SIA niet nodig heeft. hits noemt per treffer het veld (field), het soort (kind) en de term. Stuur opnieuw zonder die termen, of met confirm_free_text: true.
  • 422 pii_detectedDe tekst bevat persoonsgegevens zoals een BSN, e-mailadres of telefoonnummer. Dit kan niet worden bevestigd: haal ze weg.
  • 422 expert_review_unavailableDe triage stuurt de casus direct naar een SIA-expert (sia_human), maar expertbeoordeling staat uit voor je werkruimte. Er is niets geopend of geteld.
  • 409 reference_takenJe werkruimte heeft al een casus met deze referentie. Er is niets geanalyseerd of geteld.
  • 400 client_employer_unknownEr is geen actieve klantwerkgever met deze client_employer_id in je werkruimte.
  • 409 no_case_ownerNiemand in de werkruimte kan eigenaar van de casus zijn: de eigenaar en maker van de sleutel zijn weg en er is geen actieve eigenaar.
  • 504 provider_timeoutDe analyse duurde te lang en is gestopt. Er is niets geteld; probeer het opnieuw.
  • 400 invalid_jsonDe body is geen leesbare JSON.
  • 403 plan_requiredDe API hoort niet bij het abonnement van deze werkruimte (alleen Organisation).
  • 403 module_disabledDe API-module staat uit voor deze werkruimte.
  • 403 workspace_suspendedSIA heeft deze werkruimte gepauzeerd; de sleutels werken tijdelijk niet.
  • 500 analysis_failedDe analyse is aan onze kant misgegaan. Er is niets geteld; probeer het opnieuw.

Scopes en vervaldatum

Een sleutel mag alleen wat je hem bij het aanmaken geeft. Sleutels van vóór deze versie hebben beide scopes en verlopen niet.

WaardeBetekenis
analysis:writeCasussen laten analyseren met POST /api/v1/intelligence. Telt mee voor verbruik.
analysis:readOpgeslagen analyses ophalen met GET /api/v1/intelligence/{case_id}.

Een sleutel kan een laatste geldige dag krijgen. Daarna antwoordt elke aanroep 401 met code key_expired; een sleutel zonder de juiste scope krijgt 403 met code insufficient_scope. Bij elke aanroep worden het tijdstip en het IP-adres bewaard, zodat je in Instellingen ziet welke sleutel nog gebruikt wordt.

Idempotentie

Een analyse telt mee voor verbruik, dus opnieuw proberen na een time-out mag niet dubbel tellen. Stuur daarom bij POST een Idempotency-Key-header mee: een eigen, unieke waarde per casus, zoals een UUID.

  • Dezelfde sleutel met dezelfde body binnen 24 uur geeft het opgeslagen antwoord terug, met de header Idempotent-Replayed: true. Er wordt niets opnieuw geanalyseerd of afgeschreven.
  • Dezelfde sleutel met een andere body geeft 422 met code idempotency_mismatch.
  • Loopt de eerste aanroep nog, dan volgt 409 met code idempotency_in_progress. Probeer het na een paar seconden opnieuw.
  • Alleen een geslaagde analyse wordt bewaard. Na een fout is de sleutel weer vrij, zodat je dezelfde sleutel opnieuw kunt gebruiken.

Aanroep met Idempotency-Key

curl -X POST https://sia.example.com/api/v1/intelligence \
  -H "Authorization: Bearer sia_YOUR_KEY" \
  -H "Idempotency-Key: 6f1d2c0e-4b8a-4e59-9a3b-2f7c1d9e8a41" \
  -H "Content-Type: application/json" \
  -d @case.json

Webhooks

In plaats van te pollen kun je SIA een bericht laten sturen naar een https-adres van jezelf. Webhooks stel je in bij Instellingen → API.

WaardeBetekenis
analysis.completedEen analyse is klaar, via de API of via het scherm. data bevat case_id, case_date, category, confidence, escalation_required, source (api of app) en ai_generated met een ai_notice, omdat de categorie, de zekerheid en de escalatie uitvoer van SIA zijn.
expert_review.answeredEen SIA-expert heeft een vraag uit je werkruimte beantwoord. data bevat ticket_id en answer_id.
  • Elke levering is een POST met een JSON-body en de headers SIA-Event, SIA-Delivery, SIA-API-Version en SIA-Signature. Antwoord binnen 5 seconden met een 2xx-status.
  • Lukt een levering niet, dan probeert SIA het opnieuw met oplopende wachttijden (1, 4, 16, 64 en 256 minuten), tot 6 pogingen in totaal. SIA-Delivery blijft bij elke poging gelijk, zodat je dubbele leveringen kunt herkennen.
  • Na 20 mislukte pogingen op rij wordt het adres uitgeschakeld en krijgen de eigenaren van de werkruimte een e-mail. Weer inschakelen kan in Instellingen.
  • Met de knop Testbericht sturen ontvang je een webhook.test-bericht, ondertekend zoals elke echte levering.

Een levering

POST /your/endpoint HTTP/1.1
Content-Type: application/json
SIA-Event: analysis.completed
SIA-Delivery: 0b7e3c1a-5d2f-4e8b-9c6a-1f2e3d4c5b6a
SIA-API-Version: 2026-09-23
SIA-Signature: t=1758614400,v1=5d41402abc4b2a76b9719d911017c592...

{
  "id": "0b7e3c1a-5d2f-4e8b-9c6a-1f2e3d4c5b6a",
  "type": "analysis.completed",
  "created_at": "2026-09-23T08:00:00Z",
  "api_version": "2026-09-23",
  "data": {
    "case_id": "2d83f619-e968-489d-935a-362f6907de11",
    "case_date": "2026-09-10",
    "category": "answer",
    "confidence": "medium",
    "escalation_required": false,
    "source": "api",
    "ai_generated": true,
    "ai_notice": "Gegenereerd door SIA, een AI-systeem. Dit is een advies, geen besluit: een mens beoordeelt het voordat er iets gebeurt. Geen medisch of juridisch advies."
  }
}

De handtekening controleren

SIA-Signature heeft de vorm t=<unix-tijd>,v1=<hex>. v1 is een HMAC-SHA256 met het geheim van het adres als sleutel, over de tijd, een punt en de ruwe body. Reken dezelfde waarde uit, vergelijk in constante tijd en weiger berichten waarvan t meer dan vijf minuten afwijkt. Gebruik de body precies zoals ontvangen, vóór het parsen.

Node.js

import { createHmac, timingSafeEqual } from 'node:crypto';

// rawBody: the request body exactly as received, before JSON.parse.
export function verifySia(rawBody, header, secret, toleranceSeconds = 300) {
  const parts = Object.fromEntries(header.split(',').map((p) => p.split('=')));
  const t = Number(parts.t);
  if (!Number.isInteger(t) || Math.abs(Date.now() / 1000 - t) > toleranceSeconds) return false;
  const expected = createHmac('sha256', secret).update(`${t}.${rawBody}`).digest();
  const given = Buffer.from(parts.v1 ?? '', 'hex');
  return given.length === expected.length && timingSafeEqual(given, expected);
}

Python

import hashlib, hmac, time

# raw_body: the request body as bytes, exactly as received.
def verify_sia(raw_body: bytes, header: str, secret: str, tolerance: int = 300) -> bool:
    parts = dict(p.split("=", 1) for p in header.split(","))
    t = int(parts.get("t", "0"))
    if abs(time.time() - t) > tolerance:
        return False
    signed = f"{t}.".encode() + raw_body
    expected = hmac.new(secret.encode(), signed, hashlib.sha256).hexdigest()
    return hmac.compare_digest(expected, parts.get("v1", ""))

Versies en uitfasering

Elk antwoord van /api/v1 draagt de header SIA-API-Version: 2026-09-23. Velden toevoegen, nieuwe events en nieuwe foutcodes gebeuren binnen deze versie; lees daarom velden die je niet kent niet als fout. Alles wat een bestaande integratie kan breken, komt in een nieuwe versie met een nieuwe datum.

Een versie of veld dat verdwijnt, kondigen we minstens 12 maanden van tevoren aan, op deze pagina en per e-mail aan de eigenaren van werkruimtes met een actieve sleutel.