1509 lines
31 KiB
Plaintext
1509 lines
31 KiB
Plaintext
---
|
|
title: "FHIR REST API"
|
|
category: "fhir-api"
|
|
group: "architecture"
|
|
version: "2.0.0"
|
|
releaseDate: "2024-11-21"
|
|
status: "in-progress"
|
|
description: "RESTful FHIR API endpoints voor data-uitwisseling - patiënten, contactmomenten, diagnoses en behandelplannen"
|
|
---
|
|
|
|
## Overview
|
|
|
|
Het Mini-EPD biedt een **RESTful FHIR API** voor uitwisseling van GGZ-gegevens. De API volgt de FHIR R4 specificatie en ondersteunt standaard HTTP methods (GET, POST, PUT) voor CRUD operaties.
|
|
|
|
**Waarom een FHIR API?**
|
|
- ✅ **Data-uitwisselbaarheid** - Andere systemen kunnen jouw data lezen/schrijven
|
|
- ✅ **Standaard compliant** - Volgt internationale FHIR R4 specificatie
|
|
- ✅ **Toekomstbestendig** - Compatible met MedMIJ, Koppeltaal, LSP
|
|
- ✅ **Veilig** - Bearer token authenticatie, RLS policies, audit logging
|
|
|
|
**API Base URL:**
|
|
```
|
|
https://jouw-domein.nl/api/fhir/
|
|
```
|
|
|
|
**Response Format:**
|
|
- Content-Type: `application/fhir+json`
|
|
- FHIR R4 compliant JSON
|
|
- Errors via FHIR OperationOutcome
|
|
|
|
---
|
|
|
|
## Implementatie Status
|
|
|
|
### ✅ Epic 2: Voltooid (21 november 2024)
|
|
|
|
**Patient API** - CRUD voor patiëntgegevens
|
|
- GET, POST, PUT volledig werkend
|
|
- Zoeken op naam, BSN, geboortedatum
|
|
- FHIR Bundle responses
|
|
|
|
**Practitioner API** - Behandelaren beheer
|
|
- GET, POST werkend
|
|
- Zoeken op naam, BIG, AGB
|
|
- Nederlandse identificatie systemen
|
|
|
|
### ⏳ Epic 3-7: In Planning
|
|
|
|
**Encounter API** - Contactmomenten (Q1 2025)
|
|
**Condition API** - Diagnoses DSM-5/ICD-10 (Q1 2025)
|
|
**Observation API** - ROM-metingen & risico's (Q1 2025)
|
|
**CarePlan API** - Behandelplannen 🎯 (Q1 2025)
|
|
|
|
---
|
|
|
|
## Patient API
|
|
|
|
**Status:** ✅ **Actief** (sinds 21 november 2024)
|
|
|
|
### Endpoints
|
|
|
|
#### GET /api/fhir/Patient - Lijst van patiënten
|
|
|
|
**Beschrijving:**
|
|
Ophalen van alle patiënten met optionele zoekfilters.
|
|
|
|
**Query Parameters:**
|
|
- `name` - Zoeken op voor- of achternaam (case-insensitive)
|
|
- `identifier` - Zoeken op BSN
|
|
- `birthdate` - Zoeken op geboortedatum (YYYY-MM-DD)
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"resourceType": "Bundle",
|
|
"type": "searchset",
|
|
"total": 3,
|
|
"entry": [
|
|
{
|
|
"resource": {
|
|
"resourceType": "Patient",
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"identifier": [
|
|
{
|
|
"system": "http://fhir.nl/fhir/NamingSystem/bsn",
|
|
"value": "123456789",
|
|
"use": "official"
|
|
}
|
|
],
|
|
"name": [
|
|
{
|
|
"use": "official",
|
|
"family": "de Vries",
|
|
"given": ["Jan", "Peter"]
|
|
}
|
|
],
|
|
"gender": "male",
|
|
"birthDate": "1985-03-15",
|
|
"telecom": [
|
|
{
|
|
"system": "phone",
|
|
"value": "+31612345678",
|
|
"use": "mobile"
|
|
}
|
|
],
|
|
"active": true
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Gebruik:**
|
|
```bash
|
|
# Alle patiënten
|
|
GET /api/fhir/Patient
|
|
|
|
# Zoeken op naam
|
|
GET /api/fhir/Patient?name=vries
|
|
|
|
# Zoeken op BSN
|
|
GET /api/fhir/Patient?identifier=123456789
|
|
```
|
|
|
|
---
|
|
|
|
#### GET /api/fhir/Patient/[id] - Specifieke patiënt
|
|
|
|
**Beschrijving:**
|
|
Ophalen van één specifieke patiënt op basis van ID.
|
|
|
|
**Path Parameters:**
|
|
- `id` - UUID van de patiënt
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"resourceType": "Patient",
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"identifier": [
|
|
{
|
|
"system": "http://fhir.nl/fhir/NamingSystem/bsn",
|
|
"value": "123456789",
|
|
"use": "official"
|
|
}
|
|
],
|
|
"name": [
|
|
{
|
|
"use": "official",
|
|
"family": "de Vries",
|
|
"given": ["Jan", "Peter"],
|
|
"prefix": ["Dhr."]
|
|
}
|
|
],
|
|
"gender": "male",
|
|
"birthDate": "1985-03-15",
|
|
"telecom": [
|
|
{
|
|
"system": "phone",
|
|
"value": "+31612345678",
|
|
"use": "mobile"
|
|
},
|
|
{
|
|
"system": "email",
|
|
"value": "jan.devries@example.com"
|
|
}
|
|
],
|
|
"address": [
|
|
{
|
|
"use": "home",
|
|
"line": ["Hoofdstraat 123"],
|
|
"city": "Amsterdam",
|
|
"postalCode": "1012 AB",
|
|
"country": "NL"
|
|
}
|
|
],
|
|
"generalPractitioner": [
|
|
{
|
|
"display": "Dr. Jansen",
|
|
"identifier": {
|
|
"system": "http://fhir.nl/fhir/NamingSystem/agb-z",
|
|
"value": "12345678"
|
|
}
|
|
}
|
|
],
|
|
"active": true,
|
|
"meta": {
|
|
"lastUpdated": "2024-11-21T10:30:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Gebruik:**
|
|
```bash
|
|
GET /api/fhir/Patient/550e8400-e29b-41d4-a716-446655440000
|
|
```
|
|
|
|
**Error Response (404):**
|
|
```json
|
|
{
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [
|
|
{
|
|
"severity": "error",
|
|
"code": "not-found",
|
|
"diagnostics": "Patient with id 550e8400-... not found"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### POST /api/fhir/Patient - Nieuwe patiënt aanmaken
|
|
|
|
**Beschrijving:**
|
|
Aanmaken van een nieuwe patiënt vanuit FHIR JSON.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"resourceType": "Patient",
|
|
"identifier": [
|
|
{
|
|
"system": "http://fhir.nl/fhir/NamingSystem/bsn",
|
|
"value": "987654321",
|
|
"use": "official"
|
|
}
|
|
],
|
|
"name": [
|
|
{
|
|
"use": "official",
|
|
"family": "Jansen",
|
|
"given": ["Marie"]
|
|
}
|
|
],
|
|
"gender": "female",
|
|
"birthDate": "1990-06-20",
|
|
"telecom": [
|
|
{
|
|
"system": "phone",
|
|
"value": "+31687654321",
|
|
"use": "mobile"
|
|
}
|
|
],
|
|
"active": true
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):**
|
|
```json
|
|
{
|
|
"resourceType": "Patient",
|
|
"id": "660e8400-e29b-41d4-a716-446655440001",
|
|
"identifier": [
|
|
{
|
|
"system": "http://fhir.nl/fhir/NamingSystem/bsn",
|
|
"value": "987654321",
|
|
"use": "official"
|
|
}
|
|
],
|
|
"name": [
|
|
{
|
|
"use": "official",
|
|
"family": "Jansen",
|
|
"given": ["Marie"]
|
|
}
|
|
],
|
|
"gender": "female",
|
|
"birthDate": "1990-06-20",
|
|
"telecom": [
|
|
{
|
|
"system": "phone",
|
|
"value": "+31687654321",
|
|
"use": "mobile"
|
|
}
|
|
],
|
|
"active": true,
|
|
"meta": {
|
|
"lastUpdated": "2024-11-21T14:25:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
**Headers:**
|
|
- `Location: /api/fhir/Patient/660e8400-e29b-41d4-a716-446655440001`
|
|
|
|
**Gebruik:**
|
|
```bash
|
|
POST /api/fhir/Patient
|
|
Content-Type: application/fhir+json
|
|
|
|
{
|
|
"resourceType": "Patient",
|
|
...
|
|
}
|
|
```
|
|
|
|
**Validatie:**
|
|
Verplichte velden:
|
|
- `resourceType` moet "Patient" zijn
|
|
- `name` moet aanwezig zijn
|
|
- `gender` moet aanwezig zijn
|
|
- `birthDate` moet aanwezig zijn
|
|
|
|
**Error Response (400 Bad Request):**
|
|
```json
|
|
{
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [
|
|
{
|
|
"severity": "error",
|
|
"code": "invalid",
|
|
"diagnostics": "Missing required field: birthDate"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### PUT /api/fhir/Patient/[id] - Patiënt bijwerken
|
|
|
|
**Beschrijving:**
|
|
Bijwerken van een bestaande patiënt.
|
|
|
|
**Path Parameters:**
|
|
- `id` - UUID van de patiënt
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"resourceType": "Patient",
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
"identifier": [
|
|
{
|
|
"system": "http://fhir.nl/fhir/NamingSystem/bsn",
|
|
"value": "123456789",
|
|
"use": "official"
|
|
}
|
|
],
|
|
"name": [
|
|
{
|
|
"use": "official",
|
|
"family": "de Vries-Bakker",
|
|
"given": ["Jan", "Peter"]
|
|
}
|
|
],
|
|
"gender": "male",
|
|
"birthDate": "1985-03-15",
|
|
"telecom": [
|
|
{
|
|
"system": "phone",
|
|
"value": "+31698765432",
|
|
"use": "mobile"
|
|
}
|
|
],
|
|
"active": true
|
|
}
|
|
```
|
|
|
|
**Response (200 OK):**
|
|
Volledige bijgewerkte Patient resource.
|
|
|
|
**Gebruik:**
|
|
```bash
|
|
PUT /api/fhir/Patient/550e8400-e29b-41d4-a716-446655440000
|
|
Content-Type: application/fhir+json
|
|
|
|
{
|
|
"resourceType": "Patient",
|
|
"id": "550e8400-e29b-41d4-a716-446655440000",
|
|
...
|
|
}
|
|
```
|
|
|
|
**Validatie:**
|
|
- ID in URL moet overeenkomen met ID in body (indien aanwezig)
|
|
- Patiënt moet bestaan (anders 404)
|
|
|
|
---
|
|
|
|
## Practitioner API
|
|
|
|
**Status:** ✅ **Actief** (sinds 21 november 2024)
|
|
|
|
### Endpoints
|
|
|
|
#### GET /api/fhir/Practitioner - Lijst van behandelaren
|
|
|
|
**Beschrijving:**
|
|
Ophalen van alle behandelaren met optionele zoekfilters.
|
|
|
|
**Query Parameters:**
|
|
- `name` - Zoeken op voor- of achternaam
|
|
- `identifier` - Zoeken op BIG-nummer of AGB-code
|
|
|
|
**Response:**
|
|
```json
|
|
{
|
|
"resourceType": "Bundle",
|
|
"type": "searchset",
|
|
"total": 2,
|
|
"entry": [
|
|
{
|
|
"resource": {
|
|
"resourceType": "Practitioner",
|
|
"id": "770e8400-e29b-41d4-a716-446655440002",
|
|
"identifier": [
|
|
{
|
|
"system": "http://fhir.nl/fhir/NamingSystem/big",
|
|
"value": "12345678901",
|
|
"use": "official"
|
|
},
|
|
{
|
|
"system": "http://fhir.nl/fhir/NamingSystem/agb-z",
|
|
"value": "87654321",
|
|
"use": "official"
|
|
}
|
|
],
|
|
"name": [
|
|
{
|
|
"use": "official",
|
|
"family": "Bakker",
|
|
"given": ["Sarah"],
|
|
"prefix": ["Dr."]
|
|
}
|
|
],
|
|
"telecom": [
|
|
{
|
|
"system": "phone",
|
|
"value": "+31201234567",
|
|
"use": "work"
|
|
},
|
|
{
|
|
"system": "email",
|
|
"value": "s.bakker@ggz-instelling.nl",
|
|
"use": "work"
|
|
}
|
|
],
|
|
"qualification": [
|
|
{
|
|
"code": {
|
|
"coding": [
|
|
{
|
|
"system": "http://terminology.hl7.org/CodeSystem/v2-0360",
|
|
"display": "GZ-psycholoog"
|
|
}
|
|
],
|
|
"text": "GZ-psycholoog"
|
|
}
|
|
}
|
|
],
|
|
"active": true
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**Gebruik:**
|
|
```bash
|
|
# Alle behandelaren
|
|
GET /api/fhir/Practitioner
|
|
|
|
# Zoeken op naam
|
|
GET /api/fhir/Practitioner?name=Bakker
|
|
|
|
# Zoeken op BIG of AGB
|
|
GET /api/fhir/Practitioner?identifier=12345678901
|
|
```
|
|
|
|
---
|
|
|
|
#### GET /api/fhir/Practitioner/[id] - Specifieke behandelaar
|
|
|
|
**Beschrijving:**
|
|
Ophalen van één specifieke behandelaar.
|
|
|
|
**Response:**
|
|
Volledige Practitioner resource met BIG, AGB, kwalificaties en contactgegevens.
|
|
|
|
**Gebruik:**
|
|
```bash
|
|
GET /api/fhir/Practitioner/770e8400-e29b-41d4-a716-446655440002
|
|
```
|
|
|
|
---
|
|
|
|
#### POST /api/fhir/Practitioner - Nieuwe behandelaar aanmaken
|
|
|
|
**Beschrijving:**
|
|
Aanmaken van een nieuwe behandelaar vanuit FHIR JSON.
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"resourceType": "Practitioner",
|
|
"identifier": [
|
|
{
|
|
"system": "http://fhir.nl/fhir/NamingSystem/big",
|
|
"value": "98765432109",
|
|
"use": "official"
|
|
}
|
|
],
|
|
"name": [
|
|
{
|
|
"use": "official",
|
|
"family": "de Jong",
|
|
"given": ["Peter"]
|
|
}
|
|
],
|
|
"qualification": [
|
|
{
|
|
"code": {
|
|
"text": "Psychiater"
|
|
}
|
|
}
|
|
],
|
|
"active": true
|
|
}
|
|
```
|
|
|
|
**Response (201 Created):**
|
|
Volledige Practitioner resource met gegenereerd ID.
|
|
|
|
**Gebruik:**
|
|
```bash
|
|
POST /api/fhir/Practitioner
|
|
Content-Type: application/fhir+json
|
|
|
|
{
|
|
"resourceType": "Practitioner",
|
|
...
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Encounter API
|
|
|
|
**Status:** ⏳ **In Planning** (Epic 3 - Q1 2025)
|
|
|
|
### Geplande Endpoints
|
|
|
|
#### GET /api/fhir/Encounter - Contactmomenten
|
|
|
|
**Doel:**
|
|
Ophalen van alle contactmomenten met zoekfilters.
|
|
|
|
**Query Parameters (gepland):**
|
|
- `patient` - Filter op patiënt ID
|
|
- `date` - Filter op datum
|
|
- `type` - Type contact (intake, behandeling, crisis)
|
|
- `status` - Status (planned, in-progress, finished)
|
|
|
|
**Use Case:**
|
|
```bash
|
|
# Alle contacten van patiënt
|
|
GET /api/fhir/Encounter?patient=550e8400-e29b-41d4-a716-446655440000
|
|
|
|
# Contacten van deze maand
|
|
GET /api/fhir/Encounter?date=ge2024-11-01&date=le2024-11-30
|
|
|
|
# Alleen intakes
|
|
GET /api/fhir/Encounter?type=intake
|
|
```
|
|
|
|
**Response (voorbeeld):**
|
|
```json
|
|
{
|
|
"resourceType": "Bundle",
|
|
"type": "searchset",
|
|
"total": 5,
|
|
"entry": [
|
|
{
|
|
"resource": {
|
|
"resourceType": "Encounter",
|
|
"id": "880e8400-...",
|
|
"status": "finished",
|
|
"class": {
|
|
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
|
|
"code": "AMB",
|
|
"display": "Ambulatory (polikliniek)"
|
|
},
|
|
"type": [
|
|
{
|
|
"coding": [
|
|
{
|
|
"code": "intake",
|
|
"display": "Intakegesprek"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"subject": {
|
|
"reference": "Patient/550e8400-...",
|
|
"display": "Jan de Vries"
|
|
},
|
|
"participant": [
|
|
{
|
|
"individual": {
|
|
"reference": "Practitioner/770e8400-...",
|
|
"display": "Dr. Sarah Bakker"
|
|
}
|
|
}
|
|
],
|
|
"period": {
|
|
"start": "2024-11-15T10:00:00Z",
|
|
"end": "2024-11-15T11:00:00Z"
|
|
},
|
|
"reasonCode": [
|
|
{
|
|
"text": "Depressieve klachten"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### POST /api/fhir/Encounter - Contact aanmaken
|
|
|
|
**Doel:**
|
|
Nieuw contactmoment registreren.
|
|
|
|
**Gebruik (voorbeeld):**
|
|
```bash
|
|
POST /api/fhir/Encounter
|
|
Content-Type: application/fhir+json
|
|
|
|
{
|
|
"resourceType": "Encounter",
|
|
"status": "planned",
|
|
"class": {
|
|
"code": "AMB"
|
|
},
|
|
"type": [
|
|
{
|
|
"coding": [
|
|
{
|
|
"code": "behandeling",
|
|
"display": "Behandelsessie"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"subject": {
|
|
"reference": "Patient/550e8400-..."
|
|
},
|
|
"participant": [
|
|
{
|
|
"individual": {
|
|
"reference": "Practitioner/770e8400-..."
|
|
}
|
|
}
|
|
],
|
|
"period": {
|
|
"start": "2024-12-01T14:00:00Z"
|
|
}
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### PUT /api/fhir/Encounter/[id] - Contact bijwerken
|
|
|
|
**Doel:**
|
|
Status en gegevens van contactmoment bijwerken (bijv. van "planned" naar "finished").
|
|
|
|
---
|
|
|
|
## Condition API
|
|
|
|
**Status:** ⏳ **In Planning** (Epic 4 - Q1 2025)
|
|
|
|
### Geplande Endpoints
|
|
|
|
#### GET /api/fhir/Condition - Diagnoses
|
|
|
|
**Doel:**
|
|
Ophalen van diagnoses per patiënt.
|
|
|
|
**Query Parameters (gepland):**
|
|
- `patient` - Filter op patiënt ID
|
|
- `clinical-status` - Filter op status (active, remission, resolved)
|
|
- `code` - Filter op DSM-5/ICD-10 code
|
|
|
|
**Use Case:**
|
|
```bash
|
|
# Alle diagnoses van patiënt
|
|
GET /api/fhir/Condition?patient=550e8400-...
|
|
|
|
# Alleen actieve diagnoses
|
|
GET /api/fhir/Condition?patient=550e8400-...&clinical-status=active
|
|
|
|
# Specifieke diagnose (F32.2)
|
|
GET /api/fhir/Condition?code=F32.2
|
|
```
|
|
|
|
**Response (voorbeeld):**
|
|
```json
|
|
{
|
|
"resourceType": "Bundle",
|
|
"type": "searchset",
|
|
"total": 2,
|
|
"entry": [
|
|
{
|
|
"resource": {
|
|
"resourceType": "Condition",
|
|
"id": "990e8400-...",
|
|
"clinicalStatus": {
|
|
"coding": [
|
|
{
|
|
"system": "http://terminology.hl7.org/CodeSystem/condition-clinical",
|
|
"code": "active"
|
|
}
|
|
]
|
|
},
|
|
"verificationStatus": {
|
|
"coding": [
|
|
{
|
|
"system": "http://terminology.hl7.org/CodeSystem/condition-ver-status",
|
|
"code": "confirmed"
|
|
}
|
|
]
|
|
},
|
|
"category": [
|
|
{
|
|
"coding": [
|
|
{
|
|
"system": "http://terminology.hl7.org/CodeSystem/condition-category",
|
|
"code": "encounter-diagnosis"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"severity": {
|
|
"coding": [
|
|
{
|
|
"code": "24484000",
|
|
"display": "Severe"
|
|
}
|
|
]
|
|
},
|
|
"code": {
|
|
"coding": [
|
|
{
|
|
"system": "http://hl7.org/fhir/sid/icd-10",
|
|
"code": "F32.2",
|
|
"display": "Depressieve episode, ernstig zonder psychotische kenmerken"
|
|
}
|
|
]
|
|
},
|
|
"subject": {
|
|
"reference": "Patient/550e8400-...",
|
|
"display": "Jan de Vries"
|
|
},
|
|
"encounter": {
|
|
"reference": "Encounter/880e8400-...",
|
|
"display": "Intake 15-11-2024"
|
|
},
|
|
"onsetDateTime": "2024-09-01",
|
|
"recordedDate": "2024-11-15T10:30:00Z",
|
|
"recorder": {
|
|
"reference": "Practitioner/770e8400-...",
|
|
"display": "Dr. Sarah Bakker"
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### POST /api/fhir/Condition - Diagnose toevoegen
|
|
|
|
**Doel:**
|
|
Nieuwe diagnose registreren met DSM-5/ICD-10 code.
|
|
|
|
---
|
|
|
|
#### PUT /api/fhir/Condition/[id] - Diagnose bijwerken
|
|
|
|
**Doel:**
|
|
Status wijzigen (bijv. van "active" naar "remission").
|
|
|
|
---
|
|
|
|
## Observation API
|
|
|
|
**Status:** ⏳ **In Planning** (Epic 6 - Q1 2025)
|
|
|
|
### Geplande Endpoints
|
|
|
|
#### GET /api/fhir/Observation - Metingen & ROM-scores
|
|
|
|
**Doel:**
|
|
Ophalen van observaties, ROM-metingen en risico-inschattingen.
|
|
|
|
**Query Parameters (gepland):**
|
|
- `patient` - Filter op patiënt ID
|
|
- `category` - Type observatie (survey, risk-assessment, vital-signs)
|
|
- `code` - LOINC code voor specifieke meting (bijv. PHQ-9)
|
|
- `date` - Datum filter
|
|
|
|
**Use Case:**
|
|
```bash
|
|
# Alle ROM-metingen van patiënt
|
|
GET /api/fhir/Observation?patient=550e8400-...&category=survey
|
|
|
|
# PHQ-9 scores
|
|
GET /api/fhir/Observation?patient=550e8400-...&code=44249-1
|
|
|
|
# Recente metingen (laatste 30 dagen)
|
|
GET /api/fhir/Observation?patient=550e8400-...&date=ge2024-10-22
|
|
```
|
|
|
|
**Response (voorbeeld - PHQ-9):**
|
|
```json
|
|
{
|
|
"resourceType": "Bundle",
|
|
"type": "searchset",
|
|
"total": 3,
|
|
"entry": [
|
|
{
|
|
"resource": {
|
|
"resourceType": "Observation",
|
|
"id": "aa0e8400-...",
|
|
"status": "final",
|
|
"category": [
|
|
{
|
|
"coding": [
|
|
{
|
|
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
|
|
"code": "survey"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"code": {
|
|
"coding": [
|
|
{
|
|
"system": "http://loinc.org",
|
|
"code": "44249-1",
|
|
"display": "PHQ-9 total score"
|
|
}
|
|
]
|
|
},
|
|
"subject": {
|
|
"reference": "Patient/550e8400-...",
|
|
"display": "Jan de Vries"
|
|
},
|
|
"effectiveDateTime": "2024-11-15T10:45:00Z",
|
|
"performer": [
|
|
{
|
|
"reference": "Practitioner/770e8400-...",
|
|
"display": "Dr. Sarah Bakker"
|
|
}
|
|
],
|
|
"valueQuantity": {
|
|
"value": 18,
|
|
"unit": "score",
|
|
"system": "http://unitsofmeasure.org",
|
|
"code": "{score}"
|
|
},
|
|
"interpretation": [
|
|
{
|
|
"coding": [
|
|
{
|
|
"system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation",
|
|
"code": "H",
|
|
"display": "High"
|
|
}
|
|
],
|
|
"text": "Matig-ernstige depressie"
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### POST /api/fhir/Observation - Meting toevoegen
|
|
|
|
**Doel:**
|
|
Nieuwe ROM-score of observatie registreren.
|
|
|
|
**Gebruik (voorbeeld - GAD-7):**
|
|
```json
|
|
{
|
|
"resourceType": "Observation",
|
|
"status": "final",
|
|
"category": [
|
|
{
|
|
"coding": [
|
|
{
|
|
"code": "survey"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"code": {
|
|
"coding": [
|
|
{
|
|
"system": "http://loinc.org",
|
|
"code": "69737-5",
|
|
"display": "GAD-7 total score"
|
|
}
|
|
]
|
|
},
|
|
"subject": {
|
|
"reference": "Patient/550e8400-..."
|
|
},
|
|
"effectiveDateTime": "2024-11-21T14:00:00Z",
|
|
"valueQuantity": {
|
|
"value": 12,
|
|
"unit": "score",
|
|
"code": "{score}"
|
|
},
|
|
"interpretation": [
|
|
{
|
|
"text": "Matige angst"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## CarePlan API
|
|
|
|
**Status:** 🎯 **In Planning** (Epic 5 - Q1 2025) - **HOOFDDOEL**
|
|
|
|
### Geplande Endpoints
|
|
|
|
#### GET /api/fhir/CarePlan - Behandelplannen
|
|
|
|
**Doel:**
|
|
Ophalen van behandelplannen met doelen en activiteiten.
|
|
|
|
**Query Parameters (gepland):**
|
|
- `patient` - Filter op patiënt ID
|
|
- `status` - Filter op status (draft, active, completed)
|
|
- `category` - Type behandelplan
|
|
|
|
**Use Case:**
|
|
```bash
|
|
# Alle behandelplannen van patiënt
|
|
GET /api/fhir/CarePlan?patient=550e8400-...
|
|
|
|
# Alleen actieve plannen
|
|
GET /api/fhir/CarePlan?patient=550e8400-...&status=active
|
|
```
|
|
|
|
**Response (voorbeeld - volledig behandelplan):**
|
|
```json
|
|
{
|
|
"resourceType": "Bundle",
|
|
"type": "searchset",
|
|
"total": 1,
|
|
"entry": [
|
|
{
|
|
"resource": {
|
|
"resourceType": "CarePlan",
|
|
"id": "bb0e8400-...",
|
|
"identifier": [
|
|
{
|
|
"system": "urn:oid:2.16.840.1.113883.2.4.3.11.999.7.6",
|
|
"value": "BP-2024-001"
|
|
}
|
|
],
|
|
"status": "active",
|
|
"intent": "plan",
|
|
"category": [
|
|
{
|
|
"coding": [
|
|
{
|
|
"code": "ggz-behandelplan",
|
|
"display": "GGZ Behandelplan"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"title": "Behandelplan Depressie",
|
|
"description": "Cognitieve gedragstherapie voor ernstige depressieve episode",
|
|
"subject": {
|
|
"reference": "Patient/550e8400-...",
|
|
"display": "Jan de Vries"
|
|
},
|
|
"period": {
|
|
"start": "2024-11-20",
|
|
"end": "2025-05-20"
|
|
},
|
|
"created": "2024-11-20T09:00:00Z",
|
|
"author": {
|
|
"reference": "Practitioner/770e8400-...",
|
|
"display": "Dr. Sarah Bakker"
|
|
},
|
|
"addresses": [
|
|
{
|
|
"reference": "Condition/990e8400-...",
|
|
"display": "F32.2 - Depressieve episode, ernstig"
|
|
}
|
|
],
|
|
"goal": [
|
|
{
|
|
"description": {
|
|
"text": "PHQ-9 score verlagen naar < 10 binnen 12 weken"
|
|
},
|
|
"target": [
|
|
{
|
|
"measure": {
|
|
"coding": [
|
|
{
|
|
"system": "http://loinc.org",
|
|
"code": "44249-1"
|
|
}
|
|
]
|
|
},
|
|
"detailQuantity": {
|
|
"value": 10,
|
|
"comparator": "<",
|
|
"unit": "score"
|
|
},
|
|
"dueDate": "2025-02-12"
|
|
}
|
|
]
|
|
},
|
|
{
|
|
"description": {
|
|
"text": "Herstel dagelijks functioneren (werk/sociaal)"
|
|
}
|
|
}
|
|
],
|
|
"activity": [
|
|
{
|
|
"detail": {
|
|
"code": {
|
|
"text": "Individuele Cognitieve Gedragstherapie (CGT)"
|
|
},
|
|
"status": "in-progress",
|
|
"scheduledTiming": {
|
|
"repeat": {
|
|
"frequency": 1,
|
|
"period": 1,
|
|
"periodUnit": "wk"
|
|
}
|
|
},
|
|
"performer": [
|
|
{
|
|
"reference": "Practitioner/770e8400-...",
|
|
"display": "Dr. Sarah Bakker"
|
|
}
|
|
],
|
|
"description": "Wekelijkse CGT sessies, totaal 12 sessies"
|
|
}
|
|
},
|
|
{
|
|
"detail": {
|
|
"code": {
|
|
"text": "ROM-meting PHQ-9"
|
|
},
|
|
"status": "scheduled",
|
|
"scheduledTiming": {
|
|
"repeat": {
|
|
"frequency": 1,
|
|
"period": 4,
|
|
"periodUnit": "wk"
|
|
}
|
|
},
|
|
"description": "Elke 4 weken PHQ-9 invullen"
|
|
}
|
|
}
|
|
]
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### POST /api/fhir/CarePlan - Behandelplan aanmaken
|
|
|
|
**Doel:**
|
|
Nieuw behandelplan opstellen met doelen en interventies.
|
|
|
|
**Gebruik (voorbeeld):**
|
|
```json
|
|
{
|
|
"resourceType": "CarePlan",
|
|
"status": "active",
|
|
"intent": "plan",
|
|
"title": "Behandelplan Angststoornis",
|
|
"subject": {
|
|
"reference": "Patient/550e8400-..."
|
|
},
|
|
"addresses": [
|
|
{
|
|
"reference": "Condition/cc0e8400-...",
|
|
"display": "F41.1 - Gegeneraliseerde angststoornis"
|
|
}
|
|
],
|
|
"goal": [
|
|
{
|
|
"description": {
|
|
"text": "GAD-7 score < 5 binnen 16 weken"
|
|
},
|
|
"target": [
|
|
{
|
|
"detailQuantity": {
|
|
"value": 5,
|
|
"comparator": "<"
|
|
},
|
|
"dueDate": "2025-03-15"
|
|
}
|
|
]
|
|
}
|
|
],
|
|
"activity": [
|
|
{
|
|
"detail": {
|
|
"code": {
|
|
"text": "Exposure therapy"
|
|
},
|
|
"status": "not-started",
|
|
"scheduledTiming": {
|
|
"repeat": {
|
|
"frequency": 1,
|
|
"period": 1,
|
|
"periodUnit": "wk"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
#### PUT /api/fhir/CarePlan/[id] - Behandelplan bijwerken
|
|
|
|
**Doel:**
|
|
Status, doelen of activiteiten van behandelplan bijwerken.
|
|
|
|
**Belangrijke use cases:**
|
|
- Status wijzigen (draft → active → completed)
|
|
- Nieuwe doelen toevoegen
|
|
- Activiteiten bijwerken
|
|
- Voortgang registreren
|
|
|
|
---
|
|
|
|
## API Documentatie & Testing
|
|
|
|
**Status:** ⏳ **In Planning** (Epic 7 - Q1 2025)
|
|
|
|
### Swagger/OpenAPI Documentatie
|
|
|
|
**Geplande features:**
|
|
- Interactieve API documentatie op `/api/docs`
|
|
- Try-it-out functionaliteit voor alle endpoints
|
|
- Request/response voorbeelden
|
|
- Schema validatie
|
|
|
|
**Voorbeeld URL:**
|
|
```
|
|
https://jouw-domein.nl/api/docs
|
|
```
|
|
|
|
### FHIR Validator
|
|
|
|
**Doel:**
|
|
Automatische validatie van alle FHIR requests/responses tegen FHIR R4 spec.
|
|
|
|
**Implementatie (gepland):**
|
|
- @hapi/fhir validator integratie
|
|
- Strikte validatie mode (optioneel)
|
|
- Duidelijke error messages bij validatiefouten
|
|
|
|
---
|
|
|
|
## Authenticatie & Autorisatie
|
|
|
|
### Bearer Token Authenticatie
|
|
|
|
**Huidige implementatie:**
|
|
- Supabase Auth sessies
|
|
- RLS (Row Level Security) op database niveau
|
|
- Behandelaren zien alleen eigen patiënten
|
|
|
|
**Headers:**
|
|
```
|
|
Authorization: Bearer {supabase-session-token}
|
|
Content-Type: application/fhir+json
|
|
```
|
|
|
|
### Toekomstige uitbreiding
|
|
|
|
**SMART-on-FHIR (gepland):**
|
|
- OAuth2 authenticatie
|
|
- Scopes voor granulaire toegangscontrole
|
|
- Support voor externe apps (MedMIJ, Koppeltaal)
|
|
|
|
**Scopes (voorbeeld):**
|
|
- `patient/*.read` - Lezen van alle patiënt resources
|
|
- `patient/Patient.read` - Alleen Patient lezen
|
|
- `patient/CarePlan.write` - CarePlans aanmaken/wijzigen
|
|
|
|
---
|
|
|
|
## Error Handling
|
|
|
|
### FHIR OperationOutcome
|
|
|
|
Alle errors worden geretourneerd als FHIR OperationOutcome resource:
|
|
|
|
**400 Bad Request - Validatiefout:**
|
|
```json
|
|
{
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [
|
|
{
|
|
"severity": "error",
|
|
"code": "invalid",
|
|
"diagnostics": "Missing required field: birthDate"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**404 Not Found - Resource niet gevonden:**
|
|
```json
|
|
{
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [
|
|
{
|
|
"severity": "error",
|
|
"code": "not-found",
|
|
"diagnostics": "Patient with id 550e8400-... not found"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
**500 Internal Server Error - Serverfout:**
|
|
```json
|
|
{
|
|
"resourceType": "OperationOutcome",
|
|
"issue": [
|
|
{
|
|
"severity": "error",
|
|
"code": "exception",
|
|
"diagnostics": "Database connection failed"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### HTTP Status Codes
|
|
|
|
| Code | Betekenis | Gebruik |
|
|
|------|-----------|---------|
|
|
| 200 | OK | Succesvolle GET/PUT |
|
|
| 201 | Created | Succesvolle POST |
|
|
| 400 | Bad Request | Validatiefout |
|
|
| 401 | Unauthorized | Geen/ongeldige authenticatie |
|
|
| 403 | Forbidden | Geen toegang tot resource |
|
|
| 404 | Not Found | Resource bestaat niet |
|
|
| 500 | Internal Server Error | Serverfout |
|
|
|
|
---
|
|
|
|
## Data-uitwisseling Scenario's
|
|
|
|
### Scenario 1: Behandelplan Delen
|
|
|
|
**Use Case:**
|
|
Een patiënt verhuist naar een andere GGZ-instelling. Het behandelplan moet worden gedeeld.
|
|
|
|
**Workflow:**
|
|
```bash
|
|
# Stap 1: Export behandelplan
|
|
GET /api/fhir/CarePlan/bb0e8400-...
|
|
→ Volledige FHIR JSON response
|
|
|
|
# Stap 2: Opslaan als bestand
|
|
careplan-export.json
|
|
|
|
# Stap 3: Import in andere instelling
|
|
POST https://andere-instelling.nl/api/fhir/CarePlan
|
|
Content-Type: application/fhir+json
|
|
|
|
{
|
|
"resourceType": "CarePlan",
|
|
... (volledige careplan data)
|
|
}
|
|
|
|
# Stap 4: Succes!
|
|
201 Created
|
|
Location: /api/fhir/CarePlan/nieuwe-id
|
|
```
|
|
|
|
**Resultaat:**
|
|
✅ Behandelplan succesvol overgedragen tussen instellingen
|
|
|
|
---
|
|
|
|
### Scenario 2: MedMIJ Patiëntenportaal
|
|
|
|
**Use Case (toekomst):**
|
|
Patiënt opent PGO-app en vraagt toegang tot eigen dossier.
|
|
|
|
**Workflow:**
|
|
```bash
|
|
# Patiënt authoriseert app via OAuth2
|
|
# App vraagt toestemming voor:
|
|
# - Lezen van diagnoses
|
|
# - Lezen van behandelplan
|
|
# - Lezen van ROM-scores
|
|
|
|
# App haalt data op:
|
|
GET /api/fhir/Condition?patient=[id]
|
|
GET /api/fhir/CarePlan?patient=[id]
|
|
GET /api/fhir/Observation?patient=[id]&category=survey
|
|
|
|
# Patiënt ziet in app:
|
|
# - Diagnose: F32.2 - Depressieve episode, ernstig
|
|
# - Behandelplan: CGT 12 sessies
|
|
# - ROM-scores: PHQ-9 timeline (18 → 14 → 10)
|
|
```
|
|
|
|
**Resultaat:**
|
|
✅ Patiënt heeft inzage in eigen dossier via standaard PGO-app
|
|
|
|
---
|
|
|
|
### Scenario 3: Koppeltaal eHealth App
|
|
|
|
**Use Case (toekomst):**
|
|
Behandelaar schrijft mindfulness app voor als onderdeel van behandelplan.
|
|
|
|
**Workflow:**
|
|
```bash
|
|
# Behandelaar maakt CarePlan met activity:
|
|
POST /api/fhir/CarePlan
|
|
{
|
|
"activity": [
|
|
{
|
|
"detail": {
|
|
"code": {
|
|
"text": "Mindfulness oefeningen via MindDistrict"
|
|
},
|
|
"status": "scheduled",
|
|
"scheduledTiming": {
|
|
"repeat": {
|
|
"frequency": 3,
|
|
"period": 1,
|
|
"periodUnit": "wk"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
]
|
|
}
|
|
|
|
# Koppeltaal sync:
|
|
# - Mini-EPD stuurt CarePlan activity naar Koppeltaal
|
|
# - Koppeltaal activeert opdracht in MindDistrict app
|
|
# - Patiënt ziet opdracht in app
|
|
# - Voortgang komt terug naar Mini-EPD via Observation
|
|
```
|
|
|
|
**Resultaat:**
|
|
✅ Naadloze integratie tussen EPD en eHealth app
|
|
|
|
---
|
|
|
|
## Performance & Schaalbaarheid
|
|
|
|
### Optimalisaties
|
|
|
|
**Database Indexes:**
|
|
- Index op `patient_id` voor snelle patient queries
|
|
- Index op `identifier` velden (BSN, BIG, AGB)
|
|
- Index op `status` velden voor filtering
|
|
|
|
**Paginering:**
|
|
```bash
|
|
# Standaard: max 50 resultaten
|
|
GET /api/fhir/Patient
|
|
|
|
# Custom page size
|
|
GET /api/fhir/Patient?_count=20
|
|
|
|
# Volgende pagina (geplande feature)
|
|
GET /api/fhir/Patient?_count=20&_offset=20
|
|
```
|
|
|
|
**Response Time Targets:**
|
|
- GET single resource: < 100ms
|
|
- GET search (50 results): < 500ms
|
|
- POST/PUT: < 200ms
|
|
|
|
---
|
|
|
|
## Roadmap
|
|
|
|
### ✅ Fase 1: Patient & Practitioner (Voltooid - November 2024)
|
|
- Patient API (GET/POST/PUT)
|
|
- Practitioner API (GET/POST)
|
|
- FHIR transforms
|
|
- Basic error handling
|
|
|
|
### ⏳ Fase 2: Encounters & Conditions (Q1 2025)
|
|
- Encounter API (GET/POST/PUT)
|
|
- Condition API (GET/POST/PUT)
|
|
- Timeline integratie
|
|
|
|
### 🎯 Fase 3: CarePlans (Q1 2025) - HOOFDDOEL
|
|
- CarePlan API (GET/POST/PUT)
|
|
- Goals embedded in JSONB
|
|
- Activities embedded in JSONB
|
|
- Voortgang monitoring
|
|
|
|
### ⏳ Fase 4: Observations (Q1 2025)
|
|
- Observation API (GET/POST)
|
|
- ROM-metingen (PHQ-9, GAD-7)
|
|
- Risico-inschattingen
|
|
|
|
### 🔮 Fase 5: API Polish (Q1 2025)
|
|
- Swagger/OpenAPI documentatie
|
|
- FHIR validator integratie
|
|
- Paginering
|
|
- Advanced search
|
|
|
|
### 🔮 Fase 6: Integraties (Q2 2025)
|
|
- MedMIJ aansluiting
|
|
- Koppeltaal support
|
|
- SMART-on-FHIR OAuth2
|
|
|
|
---
|
|
|
|
## Voor Functioneel Beheerders
|
|
|
|
### Wat betekent dit voor jou?
|
|
|
|
**Als behandelaar:**
|
|
- Je hoeft niets van deze API te weten
|
|
- UI abstracteert alle complexiteit
|
|
- Gewoon werken met patiënten en behandelplannen
|
|
|
|
**Als ICT-beheerder:**
|
|
- API is volledig FHIR-compliant
|
|
- Integraties zijn goed gedocumenteerd
|
|
- Export/import is standaard
|
|
|
|
**Als management:**
|
|
- Geen vendor lock-in
|
|
- Toekomstbestendige architectuur
|
|
- Compatible met MedMIJ/Koppeltaal
|
|
|
|
### Veelgestelde Vragen
|
|
|
|
**Q: Moet ik als behandelaar de API gebruiken?**
|
|
A: Nee, de UI doet dit automatisch. De API is voor integraties met andere systemen.
|
|
|
|
**Q: Kan ik data exporteren naar Excel?**
|
|
A: Ja, via de API kun je FHIR JSON ophalen en omzetten naar CSV/Excel.
|
|
|
|
**Q: Hoe veilig is de API?**
|
|
A: Authenticatie via tokens, RLS policies, encryptie, audit logging.
|
|
|
|
**Q: Werkt dit met ons huidige EPD?**
|
|
A: Als het EPD FHIR ondersteunt, ja. Anders via export/import.
|
|
|
|
---
|
|
|
|
## Technische Referenties
|
|
|
|
**FHIR Specificaties:**
|
|
- FHIR R4: https://hl7.org/fhir/R4/
|
|
- RESTful API: https://hl7.org/fhir/R4/http.html
|
|
- Search: https://hl7.org/fhir/R4/search.html
|
|
|
|
**Project Documentatie:**
|
|
- Transform library: `lib/fhir/transforms/`
|
|
- API routes: `app/api/fhir/`
|
|
- Bouwplan: `docs/bouwplan-pragmatisch-fhir.md`
|
|
|
|
**Tools:**
|
|
- FHIR Validator: https://validator.fhir.org/
|
|
- Postman FHIR Collection: https://www.postman.com/fhir
|
|
|
|
---
|
|
|
|
**Laatst bijgewerkt:** 21 november 2024
|
|
**Versie:** 2.0.0
|
|
**Status:** In Progress - Patient & Practitioner API Actief
|