Back to all articlesConnected Care

How to check FHIR JSON payloads

Article overview

Marcus Odell 8 min readOctober 6, 2026

Overview

Confirm a device or study payload is JSON with a FHIR resourceType, walk a Patient example, and know when you still need the official HL7 FHIR validator.

A FHIR exchange fails in boring ways long before anyone argues about profiles. A partner sends a file that is not JSON. A gateway wraps a resource in an extra object. A test fixture uses type instead of resourceType. Those mistakes waste hours because they look like integration problems when they are payload problems.

Use the free FHIR JSON checker as a first smoke test. Paste a resource, confirm it parses, and confirm the root object has a string resourceType. If that check fails, stop. Do not spend the afternoon mapping Observation codes.

This article walks through what that check is doing, a Patient example you can reproduce in the tool, three failures you will actually see, and what the page cannot tell you. It is for interoperability engineers, clinical informatics leads, and regulatory people who have to decide whether a device or study feed is even speaking HL7 FHIR yet.

Start with a smoke test, not a full validator

HL7 FHIR defines resources such as Patient, Device, Observation, and Bundle. In the JSON representation, every resource instance includes a resourceType string that names the resource. Parsers use that field to decide which resource definition to apply. If it is missing, empty, or not a string, the payload is not a recognizable FHIR resource instance.

A full check is larger than that. Cardinality, coded values, references, Bundle entries, and Implementation Guide profiles (including US Core) belong in the official HL7 FHIR validator or in your IG-specific tooling. Those tools are the right place to ask whether an Observation is a valid vital sign or whether a Device has the identifiers a hospital will accept.

The smoke test answers a narrower question: is this text JSON, is the root an object, and does that object look like a FHIR resource at all? That is the question you want answered in seconds when a vendor drops a sample into Slack or a study export lands in a shared drive.

Keep the official validator in the workflow. Use it after the payload is recognizable FHIR JSON, not instead of this first pass.

What resourceType and id actually mean

resourceType is not a friendly label. It is the discriminator. A Patient, a Device, and an Observation are different resource definitions. If you send an Observation-shaped object with "resourceType": "Patient", a FHIR parser will try to read it as a Patient and the rest of the fields will look wrong or be ignored.

id is optional at this layer. Many valid resources have one, especially when they will be referenced as Patient/example or stored on a server. Many incoming messages do not. The checker reports an id when the value is a string and otherwise says the resource has no id. Neither result means the resource is clinically complete.

Count of top-level keys is a sanity signal, not a score. A Patient with only resourceType and id can pass the smoke test and still be useless for matching a subject. A Bundle can have few top-level keys and still carry hundreds of entries underneath.

If you are exchanging device data, you will usually see Device, Observation, and Bundle first. Device describes the instrument. Observation carries measurements. Bundle packages a set of resources for a message or a search result. The smoke test treats all of them the same way at the root: they need resourceType.

Worked example: a Patient that passes

Open the FHIR JSON checker. The default payload is already a small Patient: a JSON object with resourceType "Patient", id "example", and name [{ "family": "Doe" }].

The tool should report that the text looks like a FHIR Patient, that the id is example, and that there are three top-level keys. That is the entire pass condition: valid JSON, root object, non-empty string resourceType.

Now change only resourceType to Device and leave the name array in place. The smoke test still passes, because it is not checking whether the other fields belong on a Device. That is the point of a first pass, and it is also the reason you must not treat a green result as profile conformance.

Change id from "example" to a number, or delete it. The checker will still accept the resource if resourceType remains a string. A numeric id is a useful warning for later: FHIR ids are strings. The smoke test does not fail the payload for that.

This is the same discipline we use when a site adapter first sees a partner feed, as described in Connected Patient Care Without an Integration Project Every Time: normalize into a canonical shape only after you know you are looking at FHIR resources, not after you have already copied local codes into the core model.

Worked example: three failures you will see

Failure 1: the file is not JSON. A CSV export, an XML Bundle, or a log line with a trailing comma will throw a parse error. Read the message. Fix the serialization. Do not invent a mapping.

Failure 2: the JSON is an array. A list of observations is common in ad hoc exports. FHIR JSON resources are objects. If you received an array, wrap it only if you are deliberately building a Bundle, and then the root resourceType must be Bundle. Pasting the array into the checker should fail with “JSON is not an object.”

Failure 3: the object has no string resourceType. Teams rename the field to type, nest the resource under data or payload, or send a proprietary wrapper that includes resourceType one level down. The checker looks at the root. A wrapper that looks like {"data": { "resourceType": "Observation" }} fails, and it should. Your parser will fail the same way unless you unwrap it first.

A fourth pattern is worth a mention because it looks like success. Someone sends a Bundle whose root resourceType is Bundle, with type "collection" and an entry whose nested resource is an Observation. The smoke test should say this looks like a FHIR Bundle. It will not walk entry.resource elements. Clinical content in a Bundle lives in those nested resources. If you need to know whether the Observation is valid, extract it and check it separately, then run the official validator on the Bundle.

What this check does not tell you

It does not validate cardinality, ValueSets, references, or slices. It does not know US Core, national profiles, or your own Implementation Guide. It does not prove that a Device identifier will match a hospital’s master device index. It does not prove that an Observation code is the one your intended-use file claims you output.

It also does not tell you whether the exchange is lawful. If a vendor creates, receives, maintains, or transmits electronic protected health information while hosting or transforming FHIR resources for you, a HIPAA business associate analysis usually applies in the United States. That is a contracting question, not a JSON question. Use the vendor BAA vs DPA picker for the first pass on whether you are talking about a BAA, a GDPR data processing agreement, or both.

If you are about to paste a real payload into any online tool, strip identifiers first. The checker runs in the browser on the text you paste, but your own privacy policy still applies. The HIPAA Safe Harbor scanner is a first pass for the 18 identifier types listed in the Safe Harbor method. It is not a de-identification determination.

How to use the result in a real integration

Treat the smoke test as a gate in three places.

During vendor evaluation, ask for three samples: one Patient or Device, one Observation, and one Bundle. Run each through the checker before you schedule a mapping workshop. If the samples fail, the workshop will be a debugging session.

During study or device data onboarding, run the first file from each site before you write transforms. Site-specific wrappers are common. Catching them early keeps local codes out of the canonical model.

During incident response, when a feed “suddenly” breaks, paste a redacted message. If resourceType disappeared, you have a serialization or gateway change, not a terminology change.

Once the payload is recognizable FHIR JSON, move to the official HL7 FHIR validator and to your profile pack. That is where missing status on an Observation, a bad reference, or a US Core slice failure will show up.

Use the FHIR JSON checker

Paste the next sample into the FHIR JSON checker. Confirm it is JSON with a string resourceType. Then, and only then, run the official validator and your own profile checks.

If the payload carries health information, decide the contract boundary with the vendor BAA vs DPA picker and keep identifiers out of shared examples. Interoperability starts with a payload you can parse. The rest of the FHIR stack only helps after that.