Skip to main content

FHIR and health record formats

Every health record that moves inside ABDM travels as a FHIR bundle, not a PDF in an envelope of your own design and not your database rows. This page gives the version, the profiles, the bundle shape and how to validate one; the packaging detail is in the M2 guide.

R4, with Indian profiles

ABDM uses FHIR release 4. Base FHIR is loose: it says a MedicationRequest exists, not which fields an Indian prescription must fill. That second layer is a profile, and for ABDM the profiles are published by the National Resource Centre for EHR Standards, NRCES, at nrces.in/ndhm/fhir/r4. "ABDM compliant FHIR" means R4 conforming to those profiles. Read the NRCES implementation guide for field level questions. It is not restated here.

Two ways to build any record

ShapeWhat it isWhen you use it
Simple bundleA FHIR bundle wrapping a PDF or image attachment that holds the detailYour source document is a scan, a signed PDF or an image
Structured bundleA FHIR bundle with coded health information in FHIR resourcesYour system holds the data as fields, and can code it

Both are compliant. A structured bundle is more useful to the receiver, because it can be searched rather than only displayed.

The record types

There are eight record types. Implementing all of them is mandatory for an HMIS.

Record typeWhat it holdsHI type code
Diagnostic Report RecordRadiology and laboratory reportsDiagnosticReport
Discharge Summary RecordThe discharge summary for the ABDM health data setDischargeSummary
Health Document RecordUnstructured historical records, usually uploaded by patients through a health lockerHealthDocumentRecord
Immunization RecordImmunisations, vaccine certificates and next dose recommendationsImmunizationRecord
OP Consult RecordOutpatient notes: examinations, procedures, medications and clinical adviceOPConsultation
Prescription RecordMedication advice, following Pharmacy Council of India guidelinesPrescription
Wellness RecordVitals, physical examination and general health data, often captured in a PHR appWellnessRecord
Invoice RecordPharmacy invoices, consultation invoices and other billingInvoice

The names come from M2, the codes from the M3 HI type table and the M2 error message for an invalid HI type. The two lists are not published as one table; they are paired here by name, one to one.

Two mismatches. The M3 table displays HealthDocumentRecord as "Record artifact" rather than as a health document, and omits Invoice, which appears only in the M2 error message. Check the swagger before you send Invoice in a consent request.

Which resources a record carries

The reference service on the HIU side supports these resources inside a bundle.

  • Clinical content: Observation, Condition, MedicationRequest, DocumentReference, DiagnosticReport, Procedure.
  • Context and reference entities: Medication, Practitioner, Patient, Organization, Encounter.

That is the union across record types, not a mapping. Which resources belong to which record type is not documented here. The NRCES profile for each type is the authority.

The bundle shape

Every record is a Bundle of type: document, and the first entry must be a Composition.

{
"resourceType": "Bundle",
"id": "bundle01",
"timestamp": "2020-01-01T15:32:26.605+05:30",
"type": "document",
"entry": [
{
"fullUrl": "Composition/1",
"resource": {
"resourceType": "Composition",
"id": "1",
"status": "final",
"type": {
"coding": [
{
"system": "https://ndhm.gov.in/sct",
"code": "440545006",
"display": "Prescription record"
}
]
}
}
}
]
}

That is the skeleton. The full sample, with the Organization, the Encounter and the section entries, is on M2 use cases.

Why the Composition comes first

A bundle on its own is a bag of resources. The Composition turns it into a document: what this is, who it is about, who wrote it, who attests to it, and which resources make up its sections. Without it, a receiving system has a MedicationRequest and no idea whether it belongs to a prescription, a discharge summary or a draft.

Composition.type carries the SNOMED CT code that answers "what is this". Two are documented: 440545006 for a prescription record and 721981007 for a diagnostic report. The rest have their own codes in the NRCES profiles.

The rules that fail validation

FieldRule
idUnique per bundle, and resolvable inside your own system for traceability
timestampThe time the document was issued
identifierTraces the document back to your system
typeMust be document
meta.versionIdSet it on the bundle, so updates can be checked against the latest version
entry[].fullUrlA logical URL of the form resource-type/id, resolvable inside the bundle. Never an absolute URL.
Composition.attester.partyReferences an Organization whose identifier.value is the facility's HIP id as registered in the facility registry. Mode is official.
Composition.section.entry[]Top level resources only. Referenced resources such as Patient, Encounter and Practitioner belong in the bundle, not in the section entries.

The attester rule has an environment trap. The organization identifier system is the ABDM facility registry at nhpr.abdm.gov.in for production and hspsbx.abdm.gov.in for sandbox. A bundle that passes in sandbox with the sandbox value is not right in production.

One more thing to watch. Composition.type.coding.system is https://ndhm.gov.in/sct in the sample above, while section.code.coding.system in the same sample is https://affinitydomain.in/sct. The two differ in the sample itself. Take the system values from the NRCES profile, not from the sample.

Validate before you ship

Run this procedure locally. You need JDK 8 or higher.

  1. Create a folder and download the FHIR validator CLI, version 6.2.1, from the HAPI FHIR core release. Save validator_cli.jar into it.
  2. Get a bundle to test: one your own system produced, or an NRCES example from nrces.in/ndhm/fhir/r4, switching to the JSON tab to download it.
  3. Run the validator from that folder:
java -jar validator_cli.jar <YOUR_BUNDLE_FILENAME>.json -ig https://nrces.in/ndhm/fhir/r4

It checks structural correctness, conformance to the NRCES profiles, and required fields and constraints. Editing an NRCES example that already validates towards your own data is faster than starting from an empty file.

Where this is implemented