FHIR implementers, interoperability leads, and partner diligence teams

How to validate an ABDM FHIR DocumentBundle

A reproducible walkthrough for checking an ABDM FHIR R4 DocumentBundle against NRCeS 6.5.0, separating profile errors, terminology gaps, and proof limits.

What this guide delivers

Run the same bounded checks as public CI and know exactly what a green result establishes.

11 minute readPublished 29 July 2026Updated 29 July 2026By MedicalRecords.in EditorialEditorial review: MedicalRecords.in evidence review · 29 July 2026Clinical review: Not independently clinically reviewedNext review due: 29 January 2027
01Pin

Pin the specification, package, fixture, and validator first

The current published NRCeS guide identifies ndhm.in#6.5.0 as an active release based on FHIR R4 4.0.1. Its DocumentBundle profile defines the minimum expectations for a document Bundle and the contained clinical-document context.

A reproducible run should record that package version, the fixture revision and digest, the validator version and digest, and the terminology mode. MedicalRecords.in currently declares six independently synthetic fixtures, including document-envelope-only DiagnosticReportRecord, DischargeSummaryRecord, and ImmunizationRecord examples. Retained exact public validation evidence covers all six at implementation commit 8628210.[1][2][4][9][10]

Verify the declared synthetic boundary
python3 scripts/validate_fhir_fixture_manifest.py

Expected deterministic result

FHIR fixture manifest passed: 6 declared fixtures. Any undeclared JSON fixture, live-looking ABDM identifier, profile drift, or missing non-claim makes this step fail.

02Validate

Run the official validator against the pinned NRCeS package

Use Java 21 or later and a validator_cli.jar whose version and SHA-256 digest you have checked. The repository wrapper loads FHIR 4.0.1 and ndhm.in#6.5.0, disables network terminology during the profile-and-structure phase, enables security checks, and retains one OperationOutcome per fixture.

HL7 describes validation as covering structure, cardinality, value domains, bindings, invariants, and profiles, while also warning that computable validation cannot prove every narrative or business rule. Keep that distinction visible when reporting the result.[3][5]

  • Expected validator CLI version: 6.8.1
  • Expected validator JAR SHA-256: 7d05b31196557a8ed2748d3c8a1646deba9b6600f5b6946be598949bd11eefe2
  • Expected FHIR version: 4.0.1
  • Expected implementation package: ndhm.in#6.5.0
  • Do not put production records or real identifiers into a public validator or this synthetic evidence workflow.
Run all declared fixtures from the repository root
FHIR_VALIDATOR_JAR=/absolute/path/to/validator_cli.jar \
  bash scripts/validate_fhir.sh
03Outcome

Read the machine outcome instead of trusting one exit code

The Java process can report offline terminology lookup errors even when profile structure is otherwise valid. The repository does not ignore those errors wholesale: it accepts only the exact expression-and-code pairs declared for that fixture, writes a normalized summary, and fails on every other error or fatal issue.

In retained public evidence, all six declared fixtures report profile-structure-pass with zero blocking issues. Each fixture’s declared MIME lookups remain visibly deferred to the separate networked terminology gate, where every exact fixture reports terminology-pass and both invalid controls are rejected.[5][7][8]

Inspect one profile summary and its complete OperationOutcome
python3 -m json.tool fhir/validation/health-document-record-validation-summary.json
python3 -m json.tool fhir/validation/health-document-record-operation-outcome.json

Fail-closed rule

A message is deferrable only when its severity, terminology source, validator message ID, FHIR expression, and expected MIME code all match the fixture manifest. New or broader errors block the run.

04Terminology

Validate every explicit code, language, and media type separately

The second gate inventories every explicit external Coding, CodeableConcept, language, and MIME value in each exact fixture. It uses certificate-verified stateless FHIR terminology operations, pins the SNOMED CT International edition used by the evidence, and requires invalid SNOMED and MIME controls to be rejected.

This command makes network requests to tx.fhir.org. Run it only with synthetic fixtures, review the service boundary before using another server, and retain the summary beside the fixture digest.[3][6][7][8]

  • Expected verdict for each declared fixture: terminology-pass
  • Expected negative controls: two rejected invalid values
  • Expected fixture SHA-256: an exact match with the bytes that were validated
  • Open boundary: no India-extension or broader health-information-type terminology evidence is implied.
Run the exact-fixture terminology gate
while IFS=$'\t' read -r fixture_id fixture_path; do
  python3 scripts/validate_fhir_terminology.py \
    "${fixture_path}" \
    --fixture-id "${fixture_id}" \
    --summary "fhir/validation/${fixture_id}-terminology-summary.json"
done < <(python3 scripts/validate_fhir_fixture_manifest.py --list-tsv)
05Triage

Fix the boundary that failed; do not suppress the symptom

Start with the first blocking expression and compare it with both the differential profile and the full Bundle context. A valid standalone resource can still fail when its profile, slice, reference, or document position is wrong.

If terminology fails, verify the system, version, code, display, value-set binding, and server capability separately. Do not convert a service outage or unsupported code system into a permanent pass rule.[2][3]

  1. 1Confirm Bundle.type is document and Bundle.meta.profile names the published DocumentBundle canonical.
  2. 2Confirm the first entry is the profiled Composition and every fullUrl reference resolves inside the Bundle.
  3. 3Compare the Composition profile with the intended health-information type and package version.
  4. 4Resolve each blocking cardinality, invariant, slice, or reference error before reviewing warnings.
  5. 5Run terminology independently and preserve both the positive checks and rejected negative controls.
  6. 6Add a fixture-specific deferral only when the offline error is exact, understood, separately validated, reviewed, and regression-tested.
06Evidence

Bind the claim to the exact source, run, artifact, and limits

For implementation commit 8628210, the public CI run retained the manifest, six OperationOutcomes, six profile summaries, and six terminology summaries. The exact artifact reports zero blocking profile-and-structure issues, terminology-pass, and two rejected terminology controls for every declared fixture.

That evidence proves only those synthetic examples against those named checks. It does not prove live ABDM exchange, M1/M2/M3 sandbox completion, certification, production mapping, consent enforcement, clinical validity, legal compliance, approval, endorsement, or fitness for patient care.[4][7][8]

Confirm the source revision before comparing results
git rev-parse HEAD
python3 scripts/validate_fhir_fixture_manifest.py --list-tsv

A green validator is a bounded engineering result

Pair it with workflow, identity, consent, security, clinical-safety, deployment, and external-assurance evidence before making a commercial or production claim.

Sources and evidence boundary

  1. [1]ABDM FHIR Implementation Guide 6.5.0 — National Resource Centre for EHR Standards
  2. [2]NRCeS DocumentBundle profile 6.5.0 — National Resource Centre for EHR Standards
  3. [3]Validating FHIR R4 resources — HL7 International
  4. [4]Supported synthetic fixture manifest at 8628210 — MedicalRecords.in repository
  5. [5]Pinned official-validator wrapper at 8628210 — MedicalRecords.in repository
  6. [6]Exact-fixture terminology gate at 8628210 — MedicalRecords.in repository
  7. [7]Exact public FHIR conformance CI run for 8628210 — MedicalRecords.in GitHub Actions
  8. [8]Retained six-fixture official-validator artifact for 8628210 — MedicalRecords.in GitHub Actions
  9. [9]NRCeS DischargeSummaryRecord profile 6.5.0 — National Resource Centre for EHR Standards
  10. [10]NRCeS ImmunizationRecord profile 6.5.0 — National Resource Centre for EHR Standards

Sources support the specific statements linked above. Their inclusion does not imply endorsement of MedicalRecords.in. Product evidence is labelled separately in the Trust Center. Report a correction.

Put the guide to work

Keep the source. Build the useful layer around it.