Xem bản video
1. FHIR RESTful API Overview
FHIR sử dụng RESTful API làm paradigm tương tác chính. Mỗi Resource type có một endpoint riêng, tuân theo chuẩn HTTP.
Base URL
https://fhir-server.example.com/fhir/r5
├── base URL ──────────────────┘
GET [base]/Patient/123 → Đọc Patient có id=123
POST [base]/Patient → Tạo Patient mới
PUT [base]/Patient/123 → Cập nhật Patient 123
DELETE [base]/Patient/123 → Xóa Patient 123
Tổng quan các Interactions
| Interaction | HTTP Method | URL | Mô tả |
|---|---|---|---|
| read | GET | [base]/[type]/[id] | Đọc resource |
| vread | GET | [base]/[type]/[id]/_history/[vid] | Đọc version cụ thể |
| update | PUT | [base]/[type]/[id] | Cập nhật resource |
| patch | PATCH | [base]/[type]/[id] | Cập nhật một phần |
| delete | DELETE | [base]/[type]/[id] | Xóa resource |
| create | POST | [base]/[type] | Tạo resource mới |
| search | GET / POST | [base]/[type]?params | Tìm kiếm |
| history | GET | [base]/[type]/[id]/_history | Lịch sử thay đổi |
| capabilities | GET | [base]/metadata | CapabilityStatement |
2. Create (POST)
POST /fhir/r5/Patient HTTP/1.1
Host: fhir-server.example.com
Content-Type: application/fhir+json
Prefer: return=representation
{
"resourceType": "Patient",
"name": [
{
"family": "Nguyễn",
"given": ["Văn", "A"],
"text": "Nguyễn Văn A"
}
],
"gender": "male",
"birthDate": "1990-05-15"
}
HTTP/1.1 201 Created
Location: /fhir/r5/Patient/newly-assigned-id/_history/1
ETag: W/"1"
Last-Modified: 2025-01-15T10:00:00Z
Content-Type: application/fhir+json
{
"resourceType": "Patient",
"id": "newly-assigned-id",
"meta": {
"versionId": "1",
"lastUpdated": "2025-01-15T10:00:00.000Z"
},
...
}
Conditional Create
POST /fhir/r5/Patient HTTP/1.1
If-None-Exist: identifier=http://hospital.vn/mrn|MRN12345
{...}
Chỉ tạo nếu chưa tồn tại Patient nào match điều kiện → tránh duplicate.
3. Read (GET)
GET /fhir/r5/Patient/patient-001 HTTP/1.1
Accept: application/fhir+json
Version Read (vread)
GET /fhir/r5/Patient/patient-001/_history/3 HTTP/1.1
Content Negotiation
| Accept Header | Format |
|---|---|
| application/fhir+json | JSON (khuyên dùng) |
| application/fhir+xml | XML |
| Hoặc dùng _format param | ?_format=json |
4. Update (PUT)
PUT /fhir/r5/Patient/patient-001 HTTP/1.1
Content-Type: application/fhir+json
If-Match: W/"3"
{
"resourceType": "Patient",
"id": "patient-001",
"name": [
{
"family": "Nguyễn",
"given": ["Văn", "A"],
"text": "Nguyễn Văn A"
}
],
"gender": "male",
"birthDate": "1990-05-15",
"telecom": [
{
"system": "phone",
"value": "0901234567",
"use": "mobile"
}
]
}
If-Match: W/"3" → Optimistic locking. Chỉ update nếu version hiện tại là 3. Nếu đã thay đổi → 409 Conflict.
Conditional Update
PUT /fhir/r5/Patient?identifier=http://hospital.vn/mrn|MRN12345 HTTP/1.1
{...resource body...}
5. Patch (PATCH)
JSON Patch (RFC 6902)
PATCH /fhir/r5/Patient/patient-001 HTTP/1.1
Content-Type: application/json-patch+json
[
{
"op": "add",
"path": "/telecom/-",
"value": {
"system": "email",
"value": "[email protected]",
"use": "home"
}
},
{
"op": "replace",
"path": "/active",
"value": true
}
]
FHIRPath Patch
PATCH /fhir/r5/Patient/patient-001 HTTP/1.1
Content-Type: application/fhir+json
{
"resourceType": "Parameters",
"parameter": [
{
"name": "operation",
"part": [
{"name": "type", "valueCode": "add"},
{"name": "path", "valueString": "Patient"},
{"name": "name", "valueString": "active"},
{"name": "value", "valueBoolean": true}
]
}
]
}
6. Delete (DELETE)
DELETE /fhir/r5/Patient/patient-001 HTTP/1.1
FHIR servers thường implement logical delete (đánh dấu đã xóa, giữ lại trong history) thay vì xóa vật lý.
7. History
# History của một resource
GET /fhir/r5/Patient/patient-001/_history
# History của tất cả Patient
GET /fhir/r5/Patient/_history
# History toàn server
GET /fhir/r5/_history
# Với parameters
GET /fhir/r5/Patient/patient-001/_history?_count=10&_since=2025-01-01T00:00:00Z
Response trả về Bundle type history chứa tất cả versions.
8. Search cơ bản
# Tìm Patient theo tên
GET /fhir/r5/Patient?name=Nguyen
# Tìm theo giới tính
GET /fhir/r5/Patient?gender=male
# Kết hợp nhiều tham số (AND)
GET /fhir/r5/Patient?name=Nguyen&gender=male&birthdate=1990-05-15
# Tìm Observation theo Patient
GET /fhir/r5/Observation?subject=Patient/patient-001&category=vital-signs
# POST search (khi query string quá dài)
POST /fhir/r5/Patient/_search
Content-Type: application/x-www-form-urlencoded
name=Nguyen&gender=male
Search Response (Bundle searchset)
{
"resourceType": "Bundle",
"type": "searchset",
"total": 42,
"link": [
{
"relation": "self",
"url": "https://fhir-server.example.com/fhir/r5/Patient?name=Nguyen&_count=10"
},
{
"relation": "next",
"url": "https://fhir-server.example.com/fhir/r5?_getpages=uuid-abc&_pageId=2"
}
],
"entry": [
{
"fullUrl": "https://fhir-server.example.com/fhir/r5/Patient/patient-001",
"resource": {
"resourceType": "Patient",
"id": "patient-001"
},
"search": {
"mode": "match",
"score": 1
}
}
]
}
9. CapabilityStatement
GET /fhir/r5/metadata HTTP/1.1
Accept: application/fhir+json
CapabilityStatement (tên cũ: Conformance) mô tả khả năng của FHIR server: hỗ trợ resource types nào, interactions nào, search parameters nào.
10. HTTP Status Codes trong FHIR
| Status | Ý nghĩa |
|---|---|
| 200 OK | Read/Search/Update thành công |
| 201 Created | Create thành công |
| 204 No Content | Delete thành công |
| 304 Not Modified | Conditional read, chưa thay đổi |
| 400 Bad Request | Request không hợp lệ |
| 401 Unauthorized | Chưa xác thực |
| 403 Forbidden | Không có quyền |
| 404 Not Found | Resource không tồn tại |
| 409 Conflict | Version conflict (If-Match) |
| 410 Gone | Resource đã bị xóa |
| 412 Precondition Failed | Conditional operation failed |
| 422 Unprocessable Entity | Validation failed (OperationOutcome) |
11. Tổng kết
FHIR RESTful API tuân thủ chuẩn HTTP: POST/GET/PUT/PATCH/DELETE
Versioning — Mỗi update tạo version mới, truy xuất qua vread và history
Conditional operations — If-Match, If-None-Exist cho concurrency control
Search — Flexibility cao với nhiều parameter types, kết hợp AND/OR
CapabilityStatement — Tự mô tả khả năng server (machine-readable)