1. Overview of necessary tools
To practice FHIR effectively, you need to prepare the following tools:
| Tools | Purpose | Required? |
|---|---|---|
| HAPI FHIR Server | FHIR Server local for practice | Yes |
| Docker | Run HAPI FHIR Server | Yes |
| Postman/Bruno | Test API | Yes |
| VS Code | Editor with FHIR extensions | Yes |
| Node.js | Run SUSHI (FHIR Shorthand compiler) | Recommended |
| Java 17+ | HAPI FHIR Client library | Options |
2. Install HAPI FHIR Server with Docker
HAPI FHIR is the most popular open source FHIR Server, written in Java. The fastest way to get it running is using Docker.
Step 1: Create docker-compose.yml file
version: "3.8"
services:
hapi-fhir:
image: hapiproject/hapi:latest
container_name: hapi-fhir-server
ports:
- "8080:8080"
environment:
- hapi.fhir.fhir_version=R5
- hapi.fhir.allow_multiple_delete=true
- hapi.fhir.allow_external_references=true
- hapi.fhir.reuse_cached_search_results_millis=-1
volumes:
- hapi-data:/data/hapi
restart: unless-stopped
volumes:
hapi-data:
Step 2: Launch the server
# Tạo thư mục dự án
mkdir fhir-lab && cd fhir-lab
# Tạo docker-compose.yml (nội dung ở trên)
# Khởi chạy
docker compose up -d
# Kiểm tra log
docker compose logs -f hapi-fhir
Wait about 30-60 seconds, the server will be ready http://localhost:8080.
Step 3: Check the server
# Lấy CapabilityStatement
curl -s http://localhost:8080/fhir/metadata | jq '.fhirVersion'
# Kết quả: "5.0.0"
# Kiểm tra resource types được hỗ trợ
curl -s http://localhost:8080/fhir/metadata | jq '.rest[0].resource | length'
# Kết quả: 157 (hoặc gần đó)
HAPI FHIR Web UI
Access http://localhost:8080 to enter HAPI FHIR Web Testing UI — a web interface that allows you to perform all FHIR operations without writing code.
3. Public FHIR Test Servers
In addition to local servers, you can use public servers to test:
| Server | URL | Version | Notes |
|---|---|---|---|
| HAPI FHIR R5 | https://hapi.fhir.org/baseR5 | R5 | Public, free, reset periodically |
| HAPI FHIR R4 | https://hapi.fhir.org/baseR4 | R4 | Public, free |
| Firely Server | https://server.fire.ly | R4 | Sandbox free |
| SMART Health IT | https://launch.smarthealthit.org | R4 | SMART on FHIR sandbox |
Note: Do not post real data to public servers. Use only test/synthetic data.
4. Configure Postman for FHIR
Step 1: Create Collection
Create collection "FHIR Lab" in Postman with variable:
baseUrl=http://localhost:8080/fhir
Step 2: Create basic requests
1. CapabilityStatement (GET metadata)
GET {{baseUrl}}/metadata
Accept: application/fhir+json
2. Create Patient (POST)
POST {{baseUrl}}/Patient Content-Type: application/fhir+json Accept: application/fhir+json
{ "resourceType": "Patient", "identifier": [{ "system": "http://fhir.vn/sid/cccd", "value": "001085012345" }], "name": [{ "use": "official", "family": "Nguyễn", "given": ["Văn", "A"] }], "gender": "male", "birthDate": "1985-03-15", "address": [{ "use": "home", "line": ["123 Lê Lợi, Quận 1"], "city": "Thành phố Hồ Chí Minh", "country": "VN" }], "telecom": [{ "system": "phone", "value": "+84901234567", "use": "mobile" }] }
3. Read Patient (GET)
GET {{baseUrl}}/Patient/{{patientId}}
Accept: application/fhir+json
4. Search Patient (GET)
GET {{baseUrl}}/Patient?family=Nguyen&gender=male
Accept: application/fhir+json
5. Update Patient (PUT)
PUT {{baseUrl}}/Patient/{{patientId}}
Content-Type: application/fhir+json
Accept: application/fhir+json
5. VS Code Extensions for FHIR
Install useful extensions:
FHIR Tools (recommended)
FHIR Shorthand (SUSHI/HL7) — syntax highlighting for FSH
REST Client (Huachao Mao) — send HTTP requests directly from VS Code
JSON Path Finder — navigate large JSON
Using REST Client in VS Code
Create files fhir-test.http:
@baseUrl = http://localhost:8080/fhir
### Metadata
GET {{baseUrl}}/metadata
Accept: application/fhir+json
### Create Patient
POST {{baseUrl}}/Patient
Content-Type: application/fhir+json
{
"resourceType": "Patient",
"name": [{"family": "Trần", "given": ["Thị", "B"]}],
"gender": "female",
"birthDate": "1990-07-20"
}
### Search all patients
GET {{baseUrl}}/Patient?_count=10
Accept: application/fhir+json
Click "Send Request" above each request to send.
6. FHIR Shorthand (FSH) and SUSHI
FHIR Shorthand (FSH) is a specification language to write Profiles, Extensions, ValueSets concisely. SUSHI is a compiler that compiles FSH into FHIR resources.
Install SUSHI
# Cài Node.js (nếu chưa có)
# macOS
brew install node
# Cài SUSHI globally
npm install -g fsh-sushi
# Kiểm tra
sushi --version
Simple FSH example
Profile: VNPatient
Parent: Patient
Id: vn-patient
Title: "Vietnam Core Patient Profile"
Description: "Profile cho bệnh nhân Việt Nam"
* identifier 1..* MS
* identifier ^slicing.discriminator.type = #pattern
* identifier ^slicing.discriminator.path = "system"
* identifier ^slicing.rules = #open
* identifier contains cccd 0..1 MS
* identifier[cccd].system = "http://fhir.vn/sid/cccd"
* identifier[cccd].value 1..1
* name 1..* MS
* gender 1..1 MS
* birthDate 1..1 MS
FSH will be used extensively in lesson 13 (Profiles) and lesson 20 (Implementation Guide).
7. Practice: First CRUD operations
Now, let's practice basic operations on HAPI FHIR Server.
7.1. Create Patient (CREATE)
curl -X POST http://localhost:8080/fhir/Patient \
-H "Content-Type: application/fhir+json" \
-d '{
"resourceType": "Patient",
"identifier": [{
"system": "http://fhir.vn/sid/cccd",
"value": "001085012345"
}],
"name": [{
"use": "official",
"family": "Nguyễn",
"given": ["Văn", "A"]
}],
"gender": "male",
"birthDate": "1985-03-15",
"address": [{
"line": ["123 Lê Lợi"],
"city": "Hồ Chí Minh",
"country": "VN"
}]
}'
Server returns 201 Created with header Location: Patient/{id}/_history/1.
7.2. Read Patient (READ)
# Thay {id} bằng id thực tế được trả về
curl -s http://localhost:8080/fhir/Patient/{id} | jq '.name[0]'
7.3. Search for Patients (SEARCH)
# Tìm theo họ
curl -s "http://localhost:8080/fhir/Patient?family=Nguyen" | jq '.total'
# Tìm theo giới tính
curl -s "http://localhost:8080/fhir/Patient?gender=male" | jq '.entry | length'
# Tìm theo identifier (số CCCD)
curl -s "http://localhost:8080/fhir/Patient?identifier=http://fhir.vn/sid/cccd|001085012345" | jq '.entry[0].resource.name'
7.4. Update Patient (UPDATE)
curl -X PUT http://localhost:8080/fhir/Patient/{id} \
-H "Content-Type: application/fhir+json" \
-d '{
"resourceType": "Patient",
"id": "{id}",
"identifier": [{
"system": "http://fhir.vn/sid/cccd",
"value": "001085012345"
}],
"name": [{
"use": "official",
"family": "Nguyễn",
"given": ["Văn", "A"]
}],
"gender": "male",
"birthDate": "1985-03-15",
"telecom": [{
"system": "phone",
"value": "+84901234567",
"use": "mobile"
}],
"address": [{
"line": ["456 Nguyễn Huệ"],
"city": "Hồ Chí Minh",
"country": "VN"
}]
}'
7.5. Delete Patient (DELETE)
curl -X DELETE http://localhost:8080/fhir/Patient/{id}
# Trả về 200 OK hoặc 204 No Content
7.6. View history (HISTORY)
# Lịch sử một resource cụ thể
curl -s http://localhost:8080/fhir/Patient/{id}/_history | jq '.entry | length'
# Lịch sử toàn bộ Patient type
curl -s "http://localhost:8080/fhir/Patient/_history?_count=5" | jq '.entry[].request.method'
8. Create batch test data
For rich practice data, use Synthea — tool to create synthetic patient data:
# Cài Synthea (cần Java 11+)
git clone https://github.com/synthetichealth/synthea.git
cd synthea
# Tạo 10 bệnh nhân
./run_synthea -p 10 --exporter.fhir.export=true
# Output sẽ nằm trong output/fhir/
ls output/fhir/
The output files are FHIR Bundle (transaction), which can be POST directly to the server:
# Upload một bundle lên server
curl -X POST http://localhost:8080/fhir \
-H "Content-Type: application/fhir+json" \
-d @output/fhir/hospitalInformation1234.json
9. Recommended project structure
fhir-lab/
├── docker-compose.yml # HAPI FHIR Server
├── http/ # REST Client files
│ ├── patient.http
│ ├── observation.http
│ └── search.http
├── fsh/ # FHIR Shorthand files
│ ├── input/
│ │ └── fsh/
│ │ ├── profiles/
│ │ ├── extensions/
│ │ └── valuesets/
│ └── sushi-config.yaml
├── sample-data/ # Dữ liệu mẫu
│ ├── patients/
│ ├── observations/
│ └── bundles/
└── scripts/ # Scripts tiện ích
├── load-data.sh
└── cleanup.sh
10. Summary
In this article, we have:
Install HAPI FHIR Server using Docker (port 8080)
Know the FHIR Test Servers public (hapi.fhir.org)
Configuration Postman and VS Code REST Client for FHIR
Install SUSHI (FHIR Shorthand compiler)
Practice CRUD operations: Create, Read, Search, Update, Delete, History
Use Synthea to create synthetic test data
Next article, we will start going deeper FHIR Resources — starting with Patient, Practitioner, Organization and Administrative Resources.