1. FHIR RESTful API Overview
FHIR uses RESTful APIs as the main interaction paradigm. Each Resource type has its own endpoint, following the HTTP standard.
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
Overview of Interactions
| Interaction | HTTP Method | URL | Description |
|---|---|---|---|
| read | GET | [base]/[type]/[id] | Read resources |
| vread | GET | [base]/[type]/[id]/_history/[vid] | Read specific version |
| update. update | PUT | [base]/[type]/[id] | Update resources |
| patch. patch | PATCH | [base]/[type]/[id] | Partial update |
| delete | DELETE | [base]/[type]/[id] | Delete resources |
| create | POST | [base]/[type] | Create new resources |
| search. search | GET/POST | [base]/[type]?params | Search |
| history. history | GET | [base]/[type]/[id]/_history | History changes |
| 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
{...}
Only create if there is no Patient that matches the condition → avoid duplicates.
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 (recommended) |
| application/fhir+xml | XML |
| Or use _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. Only update if the current version is 3. If it has changed → 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 often implement logical delete (mark deleted, retained in history) instead of physically deleting.
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 returns Bundle type history. history contains all versions.
8. Basic search
# 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 (old name: Conformance) describes the capabilities of the FHIR server: which resource types, interactions, and search parameters it supports.
10. HTTP Status Codes in FHIR
| Status | Meaning |
|---|---|
| 200 OK | Read/Search/Update successfully |
| 201 Created | Create successfully |
| 204 No Content | Deleted successfully |
| 304 Not Modified | Conditional read, not changed |
| 400 Bad Requests | Request is invalid |
| 401 Unauthorized | Not authenticated |
| 403 Forbidden | No rights |
| 404 Not Found | Resource does not exist |
| 409 Conflict | Version conflict (If-Match) |
| 410 Gone | Resource has been deleted |
| 412 Preconditions Failed | Conditional operation failed |
| 422 Unprocessable Entity | Validation failed (OperationOutcome) |
11. Summary
FHIR RESTful API complies with HTTP standard: POST/GET/PUT/PATCH/DELETE
Versioning — Each update creates a new version, accessed via vread and history
Conditional operations — If-Match, If-None-Exist for concurrency control
Search — High flexibility with many parameter types, AND/OR combinations
CapabilityStatement — Self-describing server capabilities (machine-readable)