ABDM v3 · M1–M4 implemented

Guide FHIR R4 in ABDM

FHIR in ABDM: profiles, HI types and document bundles

Every health record exchanged over ABDM is a FHIR R4 document, shaped by the Indian profiles NRCeS publishes. This guide covers the structure, the codes and the checks that decide whether a bundle is accepted.

01Which FHIR, and where

FHIR (Fast Healthcare Interoperability Resources) is HL7’s standard for health data: a catalogue of resources such as Patient, Observation and MedicationRequest, each with a defined JSON shape. ABDM uses release R4.

Base FHIR is deliberately loose, so countries constrain it with profiles. India’s are published by NRCeS, the National Resource Centre for EHR Standards, set up by the Ministry of Health and Family Welfare at C-DAC Pune. Its implementation guide defines a profile for each kind of record, such as an OP consultation record, a prescription record or a discharge summary record, plus profiles for the resources inside them. The guide is versioned; note which version you built against, because profile details change between releases.

It helps to be clear about where FHIR is used, because the word suggests more than ABDM asks for:

  • FHIR is the record format. When a Health Information Provider shares a record, the payload is a FHIR document.
  • FHIR is not the transport. Providers do not expose FHIR REST servers to each other. The ABDM APIs for linking, consent and data requests are ABDM’s own JSON, and the FHIR document travels inside them, encrypted.
  • Your database does not have to be FHIR. Most hospital systems keep their own schema and build a bundle when a record is finalised.

If you are unsure where this fits in the wider flow, the HIP versus HIU guide shows who builds bundles and who reads them.

02Anatomy of a bundle

FHIR has several bundle types. ABDM accepts only document: a self-contained, finalised record whose first entry is a Composition acting as its table of contents. HL7 describes the pattern in its documents chapter. Stripped to the parts that matter, a lab report looks like this:

{
  "resourceType": "Bundle",
  "type": "document",
  "timestamp": "2026-09-03T10:15:00.000Z",
  "identifier": { "system": "https://ndhm.in/bundle", "value": "3f1c…" },
  "meta": {
    "profile": [
      "https://nrces.in/ndhm/fhir/r4/StructureDefinition/DocumentBundle"
    ]
  },
  "entry": [
    {
      "fullUrl": "urn:uuid:9a17…",
      "resource": { "resourceType": "Composition", … }
    },
    {
      "fullUrl": "urn:uuid:5b20…",
      "resource": { "resourceType": "Patient", … }
    },
    {
      "fullUrl": "urn:uuid:c471…",
      "resource": { "resourceType": "Practitioner", … }
    },
    {
      "fullUrl": "urn:uuid:0e88…",
      "resource": { "resourceType": "DiagnosticReport", … }
    },
    {
      "fullUrl": "urn:uuid:77d2…",
      "resource": { "resourceType": "Observation", … }
    }
  ]
}

Four properties of this shape are load-bearing:

  • type is document and the bundle carries a timestamp.
  • meta.profile names the NRCeS document bundle profile, and each resource inside declares its own profile the same way. Validators key off these URLs, so a correct shape under the wrong profile is still a rejection.
  • Every entry has a unique fullUrl, usually a urn:uuid:, and other resources refer to it by exactly that string.
  • Everything referenced is included. A document is read by someone who cannot call you back. If the report points at a practitioner, that Practitioner is an entry in the bundle.

03The Composition

The Composition says what the document is, who it is about, who wrote it and how it is organised. The fields that matter most:

  • meta.profile — the NRCeS record profile for this kind of document, for example the diagnostic report record profile.
  • type — a SNOMED CT code for the kind of record. A PHR app uses it to decide how to file and display the document, so an OP consultation coded as a discharge summary lands in the wrong place in the patient’s timeline.
  • subject — a reference that must resolve to the Patient entry in the same bundle.
  • status — final for a record being shared.
  • author and custodian — the practitioner or organisation that wrote it, and the facility responsible for it.
  • section — at least one, each with its own SNOMED CT code and entry references pointing at the clinical resources.
"resource": {
  "resourceType": "Composition",
  "meta": {
    "profile": [
      "https://nrces.in/ndhm/fhir/r4/StructureDefinition/DiagnosticReportRecord"
    ]
  },
  "status": "final",
  "type": {
    "coding": [
      {
        "system": "http://snomed.info/sct",
        "code": "721981007",
        "display": "Diagnostic studies report"
      }
    ],
    "text": "Diagnostic studies report"
  },
  "subject": { "reference": "urn:uuid:5b20…" },
  "author": [ { "reference": "urn:uuid:c471…" } ],
  "title": "Complete blood count",
  "section": [
    {
      "code": { "coding": [ { "system": "http://snomed.info/sct", "code": "721981007" } ] },
      "entry": [ { "reference": "urn:uuid:0e88…" } ]
    }
  ]
}

Record profiles differ in which sections they expect. An OP consultation, for instance, has slices for chief complaints, physical examination, medications, investigations advised and follow-up, each identified by its own SNOMED CT section code. Read the profile for each record type you produce rather than generalising from one.

04Health information types

ABDM classifies records by health information type, or hiType. Consent is granted per hiType, care contexts are listed by hiType, and each hiType corresponds to one NRCeS record profile and one Composition type code:

hiTypeComposition type (SNOMED CT)Typical source
OPConsultation371530004 — Clinical consultation reportOPD visit notes
Prescription440545006 — Prescription recordMedicines prescribed
DiagnosticReport721981007 — Diagnostic studies reportLab and imaging reports
DischargeSummary373942005 — Discharge summaryInpatient discharge
ImmunizationRecord41000179103 — Immunization recordVaccinations given
HealthDocumentRecord419891008 — Record artifactScanned or unstructured documents
WellnessRecord419891008 — Record artifactVitals, lifestyle and wellness data
InvoiceNo SNOMED CT code; type text only (“Invoice Record”)Bills

Three points follow from the table. First, the Composition type code must match the hiType of the care context the record is filed under; a mismatch is a rejection. Second, HealthDocumentRecord and WellnessRecord share a code, so the profile in meta.profile is what tells them apart. Third, an invoice carries no type coding at all. Borrowing a nearby code to fill the gap files every bill as a lab report.

The hiType also appears outside the bundle. In ABDM v3 discovery and linking responses, care contexts are grouped by hiType, with the type given once at group level. A HIP building those payloads needs the hiType stored on each care context, not derived later from the bundle.

05Terminology

Structure makes a record parseable; codes make it computable. ABDM records lean on two main code systems:

  • SNOMED CT (http://snomed.info/sct) for clinical concepts: complaints, findings, diagnoses, procedures, section and document types.
  • LOINC (http://loinc.org) for laboratory tests and vital signs. Haemoglobin in blood by mass per volume, for example, is LOINC 718-7.

Units belong in UCUM where they can be expressed there, such as g/dL or mm[Hg]. The NRCeS condition profile also allows ICD-10 for diagnoses, which helps hospitals that already code discharges that way.

When you do not have a code

A CodeableConcept can carry text alone, and that is valid. In practice many Indian hospital records are typed by operators as “Hb”, “S. Creatinine” or “F.B.S.”, and a sensible approach is:

  1. Use a code the clinician or lab system supplied, if it is from a system the profile allows.
  2. Otherwise match the name against a small, verified table of common tests and diagnoses.
  3. Otherwise send the text, and keep the original words in text in every case.

Be careful with ambiguous names. “Sugar” could be fasting, random or post-prandial blood glucose, or a urine test; “albumin” could be serum or urine. Each has a different LOINC code, and choosing one silently turns an honest text record into a wrong coded one. Fuzzy matching makes this worse, not better.

06PDFs and scanned records

A great deal of Indian hospital documentation exists only on paper, or as a PDF produced by lab equipment. FHIR carries these as an Attachment: base64 data with a content type of application/pdf. Where it goes depends on the record:

  • A lab report with structured results can carry its PDF in the DiagnosticReport’s presentedForm.
  • A scanned prescription can travel as a Binary resource.
  • Anything else, such as scanned discharge papers or an outside report, is usually a DocumentReference, and a record that is only a PDF fits the HealthDocumentRecord hiType.

Validate the bytes, not the label. HMIS uploads regularly mislabel a JPEG, a Word file or an HTML error page as a PDF, and base64 stored in a text column is often truncated. Check that the decoded file starts with %PDF- and ends with a %%EOF trailer, and cap its size: the whole bundle is encrypted and pushed in one piece, so a smaller record is a more reliable transfer. A broken attachment is invisible until the patient taps it on their phone, months later.

07Why bundles get rejected

Full FHIR validation against every StructureDefinition is slow and, with national profiles, occasionally stricter than the receiving systems. The failures that actually occur are a short list, and worth checking on every bundle before it is stored:

ProblemWhat it looks likeFix
Wrong bundle typecollection or transaction instead of document, or no timestampBuild a document bundle
Composition not firstEntries sorted by resource type, or the Composition missingInsert the Composition as entry[0]
Missing profileNo NRCeS URL in meta.profileStamp profiles on the bundle, the Composition and each resource
Dangling referenceA reference that matches no fullUrl in the bundleInclude the resource, or remove the reference
Unresolved subjectThe Composition’s subject points at nothingReference the Patient entry’s fullUrl
Type mismatchComposition code disagrees with the care context’s hiTypeDerive the code from the hiType
Duplicate fullUrlTwo entries share one URN, so references are ambiguousMint a fresh UUID per entry
Invalid JSON numbersNaN or Infinity from a failed calculationReject the value before building

Timing matters as much as the checks. An error found when the record is created can be shown to the person who typed it. The same error found when a consent request arrives becomes an ERRORED care context in a transfer, a gap in the patient’s app, and nobody left who remembers the record.

08From bundle to wire

A bundle never travels in the clear. When a HIP releases records under consent, each bundle is encrypted with ABDM’s Fidelius scheme before it is pushed to the HIU:

  1. The HIU generates an ephemeral key pair and a random nonce, and sends the public key and nonce with its data request.
  2. The HIP generates its own ephemeral key pair and nonce, and performs ECDH over Curve25519 to get a shared secret.
  3. The two nonces are combined to give a salt and an initialisation vector, and HKDF-SHA256 derives a 256-bit key from the secret.
  4. The serialised bundle is sealed with AES-256-GCM, which authenticates as well as encrypts.
  5. The HIP sends the ciphertext with its own public key and nonce; the HIU repeats the derivation and decrypts.

One detail causes a disproportionate share of failed integrations. ABDM uses Curve25519 in its short-Weierstrass form, with 65-byte uncompressed public keys, as the Java BouncyCastle library exposes it. The key-agreement functions most other libraries offer for this curve work in the Montgomery form and produce a different shared secret. The encryption appears to succeed and fails only at the far end, where the HIU cannot open anything. Test against another participant’s implementation, not just your own.

09Building it in practice

A few choices save the most time:

  • Build from your own data, per hiType. Write one builder per record type you produce, fed from your existing tables, rather than a general FHIR layer for the whole HMIS.
  • Be wary of strict model libraries. Typed FHIR libraries model base R4; national extensions and slices sometimes fight them. Plain JSON plus an explicit validator for the checks above is often easier to keep correct.
  • Generate URNs at build time. Mint every fullUrl when assembling the bundle and substitute references in one pass, so dangling references cannot happen by construction.
  • Keep a test bundle per hiType and run it through your validator in CI, alongside one real bundle received from another sandbox participant.
  • Store the bundle you sent. When a patient or an auditor asks what was shared, re-generating it from today’s data gives the wrong answer.

For where FHIR generation sits among the other steps of a hospital integration, see integrating ABDM with an HMIS.

Rather not hand-build bundles? The connector accepts plain fields or your own bundle, validates it and handles the encryption; see FHIR integration and, for labs, the lab page.

FAQ Common questions

Frequently asked questions

What is NRCeS?
The National Resource Centre for EHR Standards, set up by the Ministry of Health and Family Welfare at C-DAC Pune. It publishes the FHIR implementation guide and profiles that ABDM health records conform to.
What is a FHIR document bundle?
A Bundle of type document: a Composition first, saying what the record is and who it is about, followed by every resource it references — Patient, Practitioner, observations, medications, attachments.
Which terminologies does ABDM FHIR use?
SNOMED CT for clinical concepts such as diagnoses, findings and the composition type, and LOINC for laboratory tests. Text is still valid where no code is known.

Next Keep reading

Related reading

FHIR INTEGRATION

FHIR R4 bundles to the NRCeS profiles ABDM validates

Turn OPD consultations, prescriptions, lab results and discharge summaries into ABDM-compliant FHIR R4 document bundles. Send plain JSON or a PDF and get NRCeS-profiled bundles with SNOMED CT and LOINC coding, validated before they leave the server.

FOR DIAGNOSTIC LABS

ABDM for diagnostic labs and LIS

Publish lab reports to the patient's ABHA as an ABDM Health Information Provider: DiagnosticReport FHIR bundles with LOINC-coded results and the report PDF attached, linked per order and released only under consent. Built for LIS and lab chains.

HIP INTEGRATION

Become a Health Information Provider on ABDM

Share OPD notes, prescriptions, lab reports and discharge summaries with patients' PHR apps as an ABDM Health Information Provider. Care-context linking, discovery, consent enforcement and Fidelius-encrypted transfer, handled by one connector.

GUIDE

HIP vs HIU in ABDM: who shares, and who asks

The difference between a Health Information Provider and a Health Information User in ABDM: what each implements, how consent flows between them, what an audit checks on each side, and why most hospitals end up being both.

Try it against the sandbox

Sandbox API keys are issued the moment you verify your email. Create an ABHA, link a care context and watch the webhook arrive.