- The purpose of this implementation guide is to provide essential and minimum health record artefacts that can be captured and created as per ABDM Health Data Interchange Specifications 1.0.
- This module is built using hapi fhir library for generating the fhir resources.
- For better understanding of FHIR, check here
There are two ways to get fhir-mapper application running on your system:
Install docker and docker-compose: You can install docker desktop from here to get both.
System Requirements:
Using docker-compose-fhir.yaml to bring up the server.
2. If you are facing issues with installing or running docker, then you can install individual components:
System Requirements:
- For Java17, you can check here for compatible system configurations.
- Gradle version >= 8.5 should be fine.
Recommended RAM: Systems with more than 8 GB RAM
- If you have installed docker and docker compose then you can bring the application using:
docker compose -f docker-compose-fhir.yaml up --build
- If you have chosen to install Java and gradle components, then here is how you can bring the service up:
- Go to root of this repository and start fhir-mapper by running
gradle bootrun
- Go to root of this repository and start fhir-mapper by running
- Using any of the above approaches the server will be running on port
8085
- The HI type is primarily defined based on the data being collected. However the type of interaction should also be considered.
- If the data which is collected is not defined in the structured field for any HI-type you can create a pdf and attach to the particular bundle in the documents.
| Name | Definition |
|---|---|
| DiagnosticReportRecord | The Clinical Artifact represents diagnostic reports including Radiology and Laboratory reports that can be shared across the health ecosystem. |
| DischargeSummaryRecord | Clinical document used to represent the discharge summary record for ABDM HDE data set. |
| HealthDocumentRecord | The Clinical Artifact represents the unstructured historical health records as a single or multiple Health Record Documents generally uploaded by the patients through the Health Locker and can be shared across the health ecosystem. |
| ImmunizationRecord | The Clinical Artifact represents the Immunization records with any additional documents such as vaccine certificate, the next immunization recommendations, etc. This can be further shared across the health ecosystem. |
| OPConsultRecord | The Clinical Artifact represents the outpatient visit consultation note which may include clinical information on any OP examinations, procedures along with medication administered, and advice that can be shared across the health ecosystem. |
| PrescriptionRecord | The Clinical Artifact represents the medication advice to the patient in compliance with the Pharmacy Council of India (PCI) guidelines, which can be shared across the health ecosystem. |
| WellnessRecord | The Clinical Artifact represents regular wellness information of patients typically through the Patient Health Record (PHR) application covering clinical information such as vitals, physical examination, general wellness, women wellness, etc., that can be shared across the health ecosystem. |
| InvoiceRecord | The billing artifact represents the invoice details such as pharmacy invoice, consultation invoice etc. along with the support for scanned documents attached for the patient which can be shared across the health ecosystem. |
You can validate any FHIR Bundle against the ABDM profiles (loaded via the bundled NPM package).
POSTRequest/v1/bundle/validate- Body: A valid FHIR R4 Bundle JSON.
- Response: A validation result containing issues (errors, warnings) and overall status.
The system includes an embedded H2 database with SNOMED codes used in ABDM profiles.
GETRequest/v1/snomed/{resource}- Resource types:
Condition,Procedure,Encounter,Medication-Route,Medications,Observations,Specimen,Vaccines. - Response: List of codes and displays for that resource category.
- For Swagger-ui, check here
📄 DiagnosticReportRecord
-
for the DiagnosticReportRecord bundle you need to
POSTRequest/v1/bundle/diagnostic-report
{ "bundleType": "DiagnosticReportRecord", "careContextReference": "visist 21-03-2024", "authoredOn": "2006-04-22", "patient": { "name": "Venu Ajitesh", "patientReference": "ajitesh6x", "gender": "male", "birthDate": "2001-04-27" }, "practitioners": [{ "name": "Dr.Venu Ajitesh", "practitionerId": "Predator" }], "organisation": { "facilityName": "Predator_HIP", "facilityId": "Predator_HIP" }, "encounter": "Ambula", "diagnostics": [{ "serviceName": "BloodTest", "serviceCategory": "Hematography", "result": [{ "observation": "Height", "result": "Normal", "valueQuantity": { "unit": "CM", "value": 170 } }], "conclusion": "Normal", "presentedForm": { "contentType": "application/pdf", "data": "Base64 data of the pdf" } }], "documents": [{ "type": "diagnosticReport", "contentType": "application/pdf", "data": "Base64 data of the pdf" }] } ```
🏥 DischargeSummaryRecord
-
For the DischargeSummaryRecord bundle you need to
POSTRequest/v1/bundle/discharge-summary
{ "bundleType":"DischargeSummaryRecord", //mandatory "careContextReference":"visist 21-03-2024", //mandatory "patient":{ //mandatory "name":"Venu Ajitesh", //mandatory "patientReference":"ajitesh6x", //mandatory "gender":"male", "birthDate":"2001-04-27" }, "practitioners":[{ //mandatory "name":"Dr.Venu Ajitesh", //mandatory "practitionerId":"Predator" }], "organisation":{ //mandatory "facilityName":"Predator_HIP", //mandatory "facilityId":"Predator_HIP" }, "chiefComplaints":[ { "complaint":"Sugar", //mandatory "recordedDate":"2024-05-20", //mandatory "dateRange":{ "from":"2018-04-27", "to":"2018-05-26" } } ], "physicalExaminations":[ { "observation":"Height", //mandatory "result":"Normal", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "CM", "value": 170 } } ], "allergies":[ "Walnuts" ], "medicalHistories":[ { "complaint":"Sugar", //mandatory "recordedDate":"2024-05-20", //mandatory "dateRange":{ "from":"2018-04-27", "to":"2018-05-26" } } ], "familyHistories":[ { "relationship":"Friend", //mandatory "observation":"Toxic" //mandatory } ], "authoredOn":"2024-02-03", //mandatory "medications":[ { "medicine":"Aspirin 75 mg oral tablet", //mandatory "dosage":"1-0-1", //mandatory "timing":"2-5-d", "route":"Oral", "method":"swallow", "additionalInstructions":"Take them after food", "reason": "fever" } ,{ "medicine":"Disprin", //mandatory "dosage":"0-0-1", //mandatory "timing":"1-2-d", "route":"Syrup", "method":"drink", "additionalInstructions":"Take them before food", "reason": "Cough" } ], "diagnostics":[{ "serviceName":"BloodTest", //mandatory "serviceCategory":"Hematography", //mandatory "result":[{ "observation":"Height", //mandatory "result":"Normal", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "CM", "value": 170 } }], "conclusion":"Normal", //mandatory "presentedForm":{ "contentType":"application/pdf", "data":"Base64 data of the pdf" } }], "procedures":[ { "date":"2001-04-20", //mandatory "status":"INPROGRESS", //mandatory "procedureReason":"Severe", //mandatory "outcome":"Healthy", "procedureName":"Operation" //mandatory } ], "documents":[{ "type":"Discharge record", //mandatory "contentType":"application/pdf", //mandatory "data":"Base64 data of the pdf" //mandatory }] }
📑 HealthDocumentRecord
- for the HealthDocumentRecord bundle you need to
POSTRequest/v1/bundle/health-document
{ "bundleType":"HealthDocumentRecord", //mandatory "careContextReference":"visist 21-03-2024", //mandatory "patient":{ //mandatory "name":"Venu Ajitesh", //mandatory "patientReference":"ajitesh6x", //mandatory "gender":"male", "birthDate":"2001-04-27" }, "authoredOn":"2001-04-27", //mandatory "practitioners":[{ //mandatory "name":"Dr.Venu Ajitesh", //mandatory "practitionerId":"Predator" }], "organisation":{ "facilityName":"Predator_HIP", //mandatory "facilityId":"Predator_HIP" }, "encounter":"", "documents":[{ "type":"health-document", //mandatory "contentType":"application/pdf", //mandatory "data":"Base64 data of the pdf" //mandatory }] }
💉 ImmunizationRecord
- for the ImmunizationRecord bundle you need to
POSTRequest/v1/bundle/immunization
{ "bundleType":"ImmunizationRecord", //mandatory "careContextReference":"visit-{{$isoTimestamp}}", //mandatory "authoredOn":"2022-02-14", //mandatory "patient":{ //mandatory "name":"Venu Ajitesh", //mandatory "patientReference":"ajitesh6x", //mandatory "gender":"male", "birthDate":"2001-04-27" }, "practitioners":[{ //mandatory "name":"Dr.Venu Ajitesh", //mandatory "practitionerId":"Predator" }], "organisation":{ "facilityName":"Predator_HIP", //mandatory "facilityId":"Predator_HIP" }, "immunizations":[{ //mandatory "date":"2024-06-15", //mandatory "vaccineName":"Covaxin", //mandatory "lotNumber":"IN00004", "manufacturer":"NHA", "doseNumber":"3" }], "documents":[{ "type":"immunization", //mandatory "contentType":"application/pdf", //mandatory "data":"Base64 data of the pdf" //mandatory }] }
👨⚕️ OPConsultRecord
- for the OPConsultRecord bundle you need to
POSTRequest/v1/bundle/op-consultation
{ "bundleType":"OPConsultRecord", //mandatory "careContextReference":"visist 21-03-2025", //mandatory "visitDate":"2000-06-23", //mandatory "patient":{ //mandatory "name":"Venu Ajitesh", //mandatory "patientReference":"ajitesh6x", //mandatory "gender":"male", "birthDate":"2001-04-27" }, "practitioners":[{ //mandatory "name":"Dr.Venu Ajitesh", //mandatory "practitionerId":"Predator" }], "organisation":{ "facilityName":"Predator_HIP", //mandatory "facilityId":"Predator_HIP" }, "chiefComplaints":[ { "complaint":"Sugar", //mandatory "recordedDate":"2024-05-20", //mandatory "dateRange":{ "from":"2018-04-27", "to":"2018-05-26" } } ], "physicalExaminations":[ { "observation":"Height", //mandatory "result":"Normal", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "CM", "value": 170 } } ], "allergies":[ "Walnuts" ], "medicalHistories":[ { "complaint":"Sugar", //mandatory "recordedDate":"2024-05-20", //mandatory "dateRange":{ "from":"2018-04-27", "to":"2018-05-26" } } ], "familyHistories":[ { "relationship":"Friend", //mandatory "observation":"Toxic" //mandatory } ], "serviceRequests":[ { "status":"ACTIVE", //mandatory "details":"X-RAY", //mandatory "specimen":"Jhonsons" } ], "medications":[ { "medicine":"Aspirin 75 mg oral tablet", //mandatory "dosage":"1-0-1", //mandatory "timing":"2-5-d", "route":"Oral", "method":"swallow", "additionalInstructions":"Take them after food", "reason": "fever" } ,{ "medicine":"Disprin", //mandatory "dosage":"0-0-1", //mandatory "timing":"1-2-d", "route":"Syrup", "method":"drink", "additionalInstructions":"Take them before food", "reason": "Cough" } ], "followups":[ { "serviceType":"OPConsultation", //mandatory "appointmentTime":"2024-05-20", //mandatory "reason":"General" //mandatory } ], "procedures":[ { "date":"2001-04-20", //mandatory "status":"INPROGRESS", //mandatory "procedureReason":"Severe", //mandatory "outcome":"Healthy", "procedureName":"Operation" //mandatory } ], "referrals":[ { "status":"ACTIVE", //mandatory "details":"Y-RAY", //mandatory "specimen":"Rock" //mandatory } ], "otherObservations":[ { "observation":"weight", //mandatory "result":"Over weight", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "KG", "value": 90 } } ], "documents":[{ "type":"OP record", //mandatory "contentType":"application/pdf", //mandatory "data":"Base64 data of the pdf" //mandatory }] }
💊 PrescriptionRecord
- for the PrescriptionRecord bundle you need to
POSTRequest/v1/bundle/prescription
{ "bundleType":"PrescriptionRecord", //mandatory "careContextReference":"visit-{{$isoTimestamp}}", //mandatory "authoredOn":"2001-05-22", //mandatory "encounter":"", "patient":{ //mandatory "name":"Venu Ajitesh", //mandatory "patientReference":"ajitesh6x", //mandatory "gender":"male", "birthDate":"2001-04-27" }, "practitioners":[{ //mandatory "name":"Dr.Venu Ajitesh", //mandatory "practitionerId":"Predator" }], "organisation":{ "facilityName":"Predator_HIP", //mandatory "facilityId":"Predator_HIP" }, "prescriptions":[ { "medicine":"Aspirin 75 mg oral tablet", //mandatory "dosage":"1-0-1", //mandatory "timing":"2-5-d", "route":"Oral", "method":"swallow", "additionalInstructions":"Take them after food", "reason": "fever" } ,{ "medicine":"Disprin", //mandatory "dosage":"0-0-1", //mandatory "timing":"1-2-d", "route":"Syrup", "method":"drink", "additionalInstructions":"Take them before food", "reason": "Cough" } ], "documents":[{ "type":"Prescription", //mandatory "contentType":"application/pdf", //mandatory "data":"Base64 data of the pdf" //mandatory }] }
🌿 WellnessRecord
- for the WellnessRecord bundle you need to
POSTRequest/v1/bundle/wellness-record
{ "bundleType":"WellnessRecord", //mandatory "careContextReference":"visist 21-03-2025", //mandatory "authoredOn":"2024-02-11", //mandatory "patient":{ //mandatory "name":"Venu Ajitesh", //mandatory "patientReference":"ajitesh6x", //mandatory "gender":"male", "birthDate":"2001-04-27" }, "practitioners":[{ //mandatory "name":"Dr.Venu Ajitesh", //mandatory "practitionerId":"Predator" }], "organisation":{ "facilityName":"Predator_HIP", //mandatory "facilityId":"Predator_HIP" }, "vitalSigns":[ { "observation":"Height", //mandatory "result":"Normal", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "CM", "value": 170 } } ], "bodyMeasurements":[ { "observation":"Height", //mandatory "result":"Normal", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "CM", "value": 170 } } ], "physicalActivities":[ { "observation":"Height", //mandatory "result":"Normal", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "CM", "value": 170 } } ], "generalAssessments":[ { "observation":"Height", //mandatory "result":"Normal", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "CM", "value": 170 } } ],"womanHealths":[ { "observation":"Height", //mandatory "result":"Normal", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "CM", "value": 170 } } ], "lifeStyles":[ { "observation":"Height", //mandatory "result":"Normal", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "CM", "value": 170 } } ], "otherObservations":[ { "observation":"Height", //mandatory "result":"Normal", //you can pass either result or valueQuantity not both "valueQuantity": { "unit": "CM", "value": 170 } } ], "documents":[{ "type":"Wellness record", //mandatory "contentType":"application/pdf", //mandatory "data":"Base64 data of the pdf" //mandatory }] }
🧾 InvoiceRecord
- for the InvoiceRecord bundle you need to
POSTRequest/v1/bundle/invoice
{ "bundleType": "Invoice", "careContextReference": "visit-{{$isoTimestamp}}", "invoiceDate": "2024-05-01T06:33:37.361Z", "status": "issued", "encounter": "", "patient": { "name": "Venu Ajitesh", "patientReference": "ajitesh6x", "gender": "male", "birthDate": "1940-04-27" }, "practitioners": [ { "name": "Dr.Venu Ajitesh", "practitionerId": "Predator" } ], "organisation": { "facilityName": "Predator_HIP", "facilityId": "Predator_HIP" }, "invoice": { "id": "INV-12345", // Required "status": "issued", // Required - issued | balanced | cancelled | draft | entered-in-error "type": "Pharmacy", // Required - Consultation | Pharmacy | IPD | OPD | Others "date": "2025-08-12T10:30:00+05:30", // Required "totalNet": 2000.00, // Required "totalGross": 2200.00, // Required "currency": "INR", // Required "paymentTerms": "Due in 15 days", // Optional "note": "Surgery + post-op medicines" // Optional }, "chargeItems": [ // Required - at least one { "id": "CHG-002", "productType": "medication", // medication | device | substance "chargeType": "Pharmacy", "status": "billed", // planned | billable | not-billable | aborted | billed | entered-in-error | unknown "description": "Amoxicillin 500mg", "quantity": 14, "price": [ { "priceType": "base", // base | surcharge | deduction | discount | SGST | CGST | informational "amount": "100" } ], "medication": { // Only for type=medication "medicineName": "AMOX500", "manufacturer": "ABC Pharma", "medicationForm": "tablet", "lotNumber": "ABC123", "expiryDate": "{{$isoTimestamp}}" } }, { "id": "CHG-003", "productType": "device", // medication | device | substance "chargeType": "OPD", "status": "billed", "description": "Surgical Gloves", "quantity": 5, "price": [ { "priceType": "base", // base | surcharge | deduction | discount | SGST | CGST | informational "amount": "200" } ], "device": { // Only for type=device "udiCarrier": "UDI-GLV-001", "manufacturer": "MedGlove Inc.", "modelNumber": "MG-GLV-SRG", "lotNumber": "194847-0", "serialNumber": "SN-98347", "manufactureDate": "2025-01-10", "expirationDate": "2028-01-10", "status": "active", "safety": [ "Latex Free", "Sterile" ], "deviceName": "Surgical Gloves", "note": "Used for major surgery" } }, { "id": "CHG-004", "productType": "substance", // medication | device | substance "chargeType": "IPD", "status": "billed", "description": "Lab Reagent Kit", "quantity": 1, "price": [ { "priceType": "base", // base | surcharge | deduction | discount | SGST | CGST | informational "amount": "300" } ], "substance": { // Only for type=substance "id": "", "code": "LAB-REAGENT-001", "category": "chemical", "description": "Used to treat infections", "expiry": "{{$isoTimestamp}}", "quantity": "2.0" } } ], "payment": { "method": "upi", // Optional "status":"active", // Optional "paymentDate":"", /// Optional "paidAmount": 2200.00, // Optional "transactionId": "TXN-98765" // Optional }, }
- There are two kinds of error
- Validation errors : The errors are thrown when mandatory fields are missing
{ "validationErrors": { "code": 1000, "error": [ { "field": "bundleType", "message": "must match \"WellnessRecord\"" } ] } } - Errors while creating the FHIR bundle
{ "error":{ "code":1000, "message":"Unable to parse date" } }
- Validation errors : The errors are thrown when mandatory fields are missing
- If the FHIR bundle is generated the HttpStatus will be
201 created - The authoredOn will accept date in the format of string in format :
yyyy-MM-ddoryyyy-MM-dd'T'HH:mm:ss.SSSX- UTC iso time format
- HAPI FHIR: The backbone library for FHIR R4 resource generation and validation.
- Spring Boot 3.x: High-performance web framework for the REST API layer.
- H2 Database: High-speed embedded database serving SNOMED-CT terminology.
- ABDM Profiles: Specialized FHIR profiles (IGs) loaded dynamically via the classpath.
The codebase is organized into layers to ensure separation of concerns and maintainability.
flowchart LR
%% Define reusable styling classes
classDef clientNode fill:#3498db,stroke:#2c3e50,stroke-width:2px,color:#fff;
classDef serviceNode fill:#9b59b6,stroke:#8e44ad,stroke-width:2px,color:#fff;
classDef logicNode fill:#2ecc71,stroke:#27ae60,stroke-width:2px,color:#fff;
classDef resultNode fill:#f1c40f,stroke:#f39c12,stroke-width:2px,color:#000;
subgraph Client ["🌐 Client Layer"]
direction TB
A[External System] -->|POST| B[BundleController]:::clientNode
end
subgraph Service ["⚙️ Service Layer"]
direction TB
B --> C{Orchestrator}:::serviceNode
C --> D[Prescription]
C --> E[OPConsultation]
C --> F[DiagnosticReport]
C --> G[...]
end
subgraph Logic ["🧪 Logic & Mapping"]
direction TB
H[Resource Makers]:::logicNode
I[BundleUtils]:::logicNode
end
D & E & F & G --> H
D & E & F & G --> I
subgraph Result ["📦 Result"]
J[FHIR Bundle JSON]:::resultNode
end
I --> J
style Client fill:none,stroke:#3498db,stroke-dasharray: 5 5,stroke-width:2px
style Service fill:none,stroke:#9b59b6,stroke-dasharray: 5 5,stroke-width:2px
style Logic fill:none,stroke:#2ecc71,stroke-dasharray: 5 5,stroke-width:2px
style Result fill:none,stroke:#f1c40f,stroke-dasharray: 5 5,stroke-width:2px
This matrix illustrates how various ABDM Health Information (HI) types are transformed into their respective FHIR resource collections.
flowchart TB
%% Define elegant, modern node styles (Pastel fill, bold borders, dark text)
classDef inputNode fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px,color:#000,rx:8,ry:8;
classDef coreHub fill:#e1f5fe,stroke:#0288d1,stroke-width:2px,color:#000,rx:8,ry:8;
classDef medNode fill:#fff3e0,stroke:#f57c00,stroke-width:2px,color:#000,rx:5,ry:5;
subgraph HI_Types ["📥 Input HI Types"]
direction LR
HI1([💊 Prescription]):::inputNode
HI2([🩺 OPConsultation]):::inputNode
HI3([🔬 DiagnosticReport]):::inputNode
HI4([📄 DischargeSummary]):::inputNode
HI5([💉 Immunization]):::inputNode
end
subgraph Shared_Resources ["📂 Core Resources (Shared Payload)"]
direction LR
CoreHub[["📦 Bundle<br/>━━━━━━━━━━━━━━<br/>📄 Composition<br/>👤 Patient<br/>⚕️ Practitioner<br/>🏥 Organization"]]:::coreHub
end
subgraph Specific_Resources ["⚙️ Specific Medical Resources"]
direction LR
S1[MedicationRequest]:::medNode
S2[Encounter]:::medNode
S3[Condition]:::medNode
S4[Observation]:::medNode
S5[DiagnosticReport]:::medNode
S6[Procedure]:::medNode
S7[Immunization]:::medNode
end
%% Routing logic
HI1 & HI2 & HI3 & HI4 & HI5 --->|Always Includes| CoreHub
%% Individual mapping for specific resources
HI1 --> S1
HI2 --> S2 & S3 & S4 & S1
HI3 --> S5 & S4
HI4 --> S2 & S6 & S3
HI5 --> S7
%% Subgraph Aesthetics (Transparent backgrounds, colored dashed borders, rounded corners)
style HI_Types fill:none,stroke:#7b1fa2,stroke-dasharray: 5 5,stroke-width:2px,rx:10,ry:10
style Shared_Resources fill:none,stroke:#0288d1,stroke-dasharray: 5 5,stroke-width:2px,rx:10,ry:10
style Specific_Resources fill:none,stroke:#f57c00,stroke-dasharray: 5 5,stroke-width:2px,rx:10,ry:10
This project is licensed under the Apache License 2.0. See the LICENSE file for the full text.