FHIR Bundle Viewer: How to Inspect a Bundle You Received
Hl7 Tools

FHIR Bundle Viewer: How to Inspect a Bundle You Received

The Bundle Arrived. Now What?

A vendor, a partner hospital, or a colleague sends you a FHIR Bundle and asks you to "take a look." The file is a few hundred kilobytes of nested JSON. Scrolling it in an editor tells you almost nothing useful in the first ten minutes, and the questions you actually need answered โ€” is this the right patient, is anything missing, will this load into our system โ€” are not questions you can answer by reading braces.

This is a checklist for that situation: what to look at first, in what order, and which findings should stop you from accepting the bundle. It assumes you can read JSON but have not memorised the specification. Everything here can be done in the FHIR Bundle Explorer, which parses in your browser so a bundle full of PHI never leaves your machine. If the structure of a Bundle itself is unfamiliar โ€” type, entry, fullUrl and the rest โ€” read What Is a FHIR Bundle? first, because the checks below assume you know what those parts are for.

Step One: Confirm What You Actually Received

Before anything else, establish the shape of the file. People say "bundle" loosely, and what arrives is often something else: a single bare resource, an NDJSON export from a bulk job, or a plain JSON array of resources produced by someone running jq -s over an export. All three are legitimate deliveries; none of them is a Bundle. A viewer that auto-detects the shape saves you the guessing โ€” the Bundle Explorer recognises a Bundle by its resourceType, a bare resource by having a resourceType that is not Bundle, NDJSON by being unparseable as one document while every line starts a fresh object, and a bare array by its brackets.

Knowing the shape matters because it changes what you can expect. Only a Bundle has entry-level fullUrl values, and only a Bundle has bundle-level metadata such as type and timestamp. Judging an NDJSON export against Bundle expectations produces a list of complaints about things that were never supposed to be there.

Step Two: Read the Resource Tally

The single most informative view of a new bundle is the count of resources per resourceType. It takes five seconds to read and answers most of the sanity questions at once.

Look for three things. Is anything missing entirely? A clinical summary with 40 Observations and zero Patients is missing its subject โ€” the observations reference a patient who is not in the file. Are the proportions plausible? One Patient and 3,000 Observations is normal for a monitoring feed and suspicious for a discharge summary. Are there types you did not expect? An unexpected Provenance or AuditEvent is harmless; an unexpected OperationOutcome usually means the sender's export partly failed and the error got packaged alongside the data.

Also check whether the tally is complete. A viewer that reads locally has to have limits โ€” the Bundle Explorer parses up to 25 MB and 20,000 resources โ€” and the thing that matters is whether it tells you when it hit one. It reports the number of resources dropped explicitly, so a truncated read is never mistaken for a small bundle. If you see a dropped count, get the file split at source before you draw any conclusions from the tally.

Step Three: Scan One Table per Resource Type

Reading nested JSON is a poor way to spot patterns. Reading a table is a good one. Flattening each resource type into rows and columns โ€” id, status, code, value, date, subject reference โ€” makes whole classes of problem visible at a glance rather than resource by resource.

What jumps out in a table and hides in JSON: an entire column that is empty, meaning a field you expected is absent across every record; a status column reading entered-in-error on rows nobody mentioned; dates clustered on a single implausible day, the signature of a bulk backfill or a test dataset; a value column where units are inconsistent, so some rows are in mg/dL and others in mmol/L; or a subject reference column where a handful of rows point somewhere different from all the others.

That last one deserves a specific look, because a bundle described as being about one patient should have one distinct value in its subject reference columns. Sorting that column and seeing two values is one of the highest-value five-second checks you can run on a clinical bundle. If you want to take the table further โ€” into a spreadsheet for reconciliation โ€” the choices around repeating values and safe Excel import are covered in How to Convert a FHIR Bundle to CSV Without Losing Data.

Step Four: Follow the References

A Bundle is a graph, not a list. Its meaning lives in the edges: an Observation points at its subject, an Encounter at its patient and its service provider, a Condition at both the patient and the encounter in which it was recorded. Inspecting the nodes without inspecting the edges tells you the data exists but not whether it hangs together.

Practically, navigating references means being able to click a reference and land on the resource it names, and โ€” just as usefully โ€” being able to ask which resources point at the one you are looking at. Incoming references are how you answer "what do we actually know about this patient in this file": select the Patient and the Observations, Conditions, Encounters and MedicationRequests that reference it are the answer. It is also how you spot orphans, resources that nothing points at and which point at nothing, which usually arrived by accident.

Resolution inside a bundle uses more than one key, which is worth knowing so the results are not surprising. A resource is addressable by resourceType/id โ€” the relative reference form โ€” and, when the entry carries one, by its fullUrl. That second key is what makes urn:uuid: references work: a transaction bundle assembled before the server assigned real ids uses UUIDs as temporary identity, with each entry's fullUrl holding the UUID and references pointing at it. Because a fullUrl like http://example.org/fhir/Patient/123 also ends in a usable relative form, its trailing Patient/123 is treated as an address too, which is how entries in the same bundle usually refer to one another. Where two resources claim the same key, the first one wins, so a duplicate id cannot hijack an earlier resource.

FHIR Bundle Viewer: How to Inspect a Bundle You Received

Step Five: Look Hard at Unresolved References

An unresolved reference is one whose target is not present in what you loaded. This is the single most common defect in a delivered bundle and the one most likely to break the receiving system, so it deserves its own pass.

It is essential that a viewer surfaces these rather than quietly ignoring them, and equally essential that it does not try to fix them by fetching. The Bundle Explorer resolves references locally only and never makes a network request to chase one down. That is a privacy decision, not a missing feature: a reference string contains an identifier, and asking an external server about it discloses that a particular record is being looked up โ€” exactly the kind of leak that a local-processing tool exists to prevent.

Not every unresolved reference is a bug, though, and mistaking a legitimate one for a defect wastes a lot of time. Work through these causes in order:

  • The target genuinely was not sent. An Observation referencing Patient/123 in a bundle containing no Patient. This is a real defect if the bundle was supposed to be self-contained โ€” go back to the sender.
  • The reference is absolute and external by design. A pointer to a Practitioner or Organization on the sender's server, deliberately not included because it is shared reference data rather than patient data. Correct behaviour, nothing to fix.
  • You are looking at one file of a multi-file export. In a bulk export split per resource type, an Observation's subject reference cannot resolve while you are viewing only the Observation file. Expected, not a defect.
  • A urn:uuid: reference with no matching fullUrl. The bundle uses temporary identity but the entry that should carry the matching UUID is absent or was assembled wrongly. This is a genuine construction bug and will fail on submission.
  • A near-miss in the reference string. Wrong capitalisation of the resource type, a trailing slash, a version suffix like Patient/123/_history/2 where the plain form was expected. Easy to fix once seen, invisible until you look.

The distinctions between these forms โ€” relative, absolute, UUID, contained โ€” are worth internalising if you handle bundles regularly; How FHIR References Work goes through each one and when each is appropriate.

What a Viewer Deliberately Does Not Do

Being clear about scope prevents a false sense of assurance. A bundle viewer is read-only: it parses, tabulates, indexes references and exports, and it never modifies the input. It also does not validate. A resource missing a required element, carrying a code from the wrong system, or violating a profile's slicing rules will display perfectly happily โ€” the viewer's job is to show you what is there, not to judge it against a StructureDefinition. Conformance checking is a separate discipline with its own failure vocabulary, covered in Understanding FHIR Validator Cardinality and Slicing Errors.

One more scope note: the explorer works with JSON only, not the XML serialisation. In practice this is rarely a constraint, since JSON dominates FHIR exchange and every bulk export is JSON by specification, but if a partner sends XML you will need to convert before inspecting.

Why "Online Viewer" Should Mean "In Your Browser"

Most search results for a bundle viewer are hosted services that upload your file to a server for processing. For a synthetic test bundle that is fine. For a real one it is a disclosure of protected health information to a third party, made casually, usually without a business associate agreement, and often repeated a dozen times over an afternoon of debugging. The distinction that matters is not whether a tool is online โ€” it is whether processing happens on their machine or yours. A tool that parses in JavaScript in your tab is online in the sense that you reach it over the web and local in the sense that your data stays put, and you can confirm the second part yourself in the browser's network panel.

Conclusion

Inspecting a bundle you received is a five-step routine: confirm the shape, read the resource tally, scan a table per type, follow the references in both directions, then work through the unresolved ones and classify each as a real defect or an expected external pointer. Most of the problems that break a downstream load โ€” a missing subject, a duplicated patient, a truncated file, a broken urn:uuid: โ€” surface in those five steps in under ten minutes. Run them in the FHIR Bundle Explorer, remember that it reads rather than validates, and you can do the whole review with the patient data never leaving your machine.

← Back to Blog