Handle FHIR identifiers and match patient data

Last updated: Apr 25, 2025
DEVELOPER
HEALTH TECH VENDOR
HCO
IMPLEMENTATION

One benefit of FHIR® is that it’s flexible, but that can also be a challenge. Matching patient records to the appropriate data is a critical part of data exchange, but how do you do that with flexible, non-static identifiers?

Spoiler alert: You should use patient identifiers and demographics to match data appropriately.

For more details, let’s break down some of the identifiers you’ll come across in a FHIR® schema.

Identifier vs. ID

An identifier is an external business identifier, meaning it’s created and maintained by a system outside the FHIR® server. An identifier has an associated system and value. The system defines the format and interpretation of the value. The system identifies the external system and should be expressed in a FHIR® payload as a URI. For example, a Social Security number is a type of identifier for a patient record, and the external system defines that it should be a numeric value with nine digits, as well as assigns the specific value.

A FHIR® ID is an internal identifier for a resource. When a resource is stored in a database, it’s referenced using the resource ID. For data on demand, this is going to be a UUID.

What Redox or your connection generates

In a FHIR® notification, the ID is generated randomly. Any identifiers are pulled from the connection’s system, not Redox.

In a FHIR® query, the database or server returning the response provides the ID. Redox may randomly generate this value if there’s any translation from one format to another. Any identifiers are pulled from the connection’s system, not Redox.

Identifiers for patient data

In FHIR®, you’ll come across a lot of identifiers related to clinical data, like identifiers for patients, encounters, labs, practitioners, documents, and more. These are external identifiers that generally stay static throughout the patient care lifecycle. In a FHIR® schema, identifiers are your safest option for matching clinical data to the correct patient record. That also means you should include these identifiers when you’re sending your own clinical data to your connection so they can appropriately match the data, too.

We recommend including the system with the identifier whenever performing FHIR® queries or writeback.

Additionally, there are a couple of other fields in a FHIR® schema that help you understand the context of identifiers. These are the use and type fields. The use field describes the identifier’s purpose. If the use value is official, you can count on that being the primary identifier. All the others are secondary to that one. The type field gives context for the system where that identifier is meaningful.

Don't make assumptions

We can't guarantee the order of identifiers in an array. That means that the primary identifier—or the best one for your use case—may not necessarily be the first in the list.

So don't assume that the first identifier in the array is the one you want. Use the context fields for the identifier to determine if it's the right one.

FHIR® resource IDs

A FHIR® resource ID is an internal identifier within a FHIR® server. While a resource may represent data, the resource itself is an independent concept with its own ID. For example, there could be two resources representing the same data because different systems have records for the same data.

You can think of a resource ID as a QR code on a shipping label. The QR code represents a unique package being shipped (i.e., FHIR® message), but not necessarily the individual pieces inside the package (i.e., the included data). The resource ID identifies the unique resource (or package) representing clinical data, not any of the data inside.

If the data exchange happens between FHIR® servers, you may use the resource ID to query for a specific FHIR® resource. Using our shipping label example, the QR code works at different UPS locations, but it won’t work at a FedEx location. So, unless you’re querying a FHIR® server directly, you can’t retrieve specific clinical data with a resource ID.

How resource IDs apply to Redox

Redox isn’t a FHIR® server. So resource IDs don’t stay static when you’re querying via Redox. A query response contains a resource ID, but you shouldn’t plan to use it to query for the same data later.

Data on demand

You may be able to successfully query for data with the resource ID if you're querying a data on demand instance. However, it's only likely to work if you've recently received or queried for the same data.

The resource ID may change in the case of a patient merge or other patient updates. So a resource ID isn't guaranteed to work with data on demand.

Within FHIR® notifications, resource IDs are generated randomly for each message, so they’re not consistent across notifications. Those resource IDs in a bundle will be consistent within that message itself, and may be used to reference another resource only within that bundle.

Full URLs

A full URL is a randomly generated UUID that identifies a FHIR® resource. If you see a full URL instead of a resource ID, it typically means the resource doesn’t have an ID. Or if it does, the destination ignores the value.

Generally, the full URL links related resources together in a bundle. All the resources in the bundle will contain that same URL. However, the URL will be static throughout the bundle for that one-time message, not for the lifecycle of that message or for related data outside of the bundle.

So, a FHIR® notification bundle has a consistent fullURL across the resources in that bundle. If the notification were re-sent, though, the fullURL would be different.

How full URLs apply to Redox

Redox typically uses message bundles with randomly generated full URLs. They’re not consistent across messages, even if we’re sending the same resource again later.

A bundle story

For a bedtime story of how bundles work, keep reading!

A FHIR® bundle with a message or document type is like a package Redox ships to a customer. The package contains a bunch of items (resources) that go in the box with a packing list (MessageHeader) on top. Since the items in the box are related, we package each item with one or more strands (references and fullUrls) tied to the related item. If you pull on just the packing list (MessageHeader), you’ll end up with an entire “tree” of items all tied together.

When you receive the package, we don’t know how you’re going to use the items inside. You might just pull out the wad of items still tied together and store it as-is on a shelf (i.e., saving the bundle as a standalone message).

More likely, you'll use the items inside the package to stock your warehouse (data store). It's up to you to hire an inventory manager (FHIR® API engine), whose job is to unpack and organize the packages. This involves checking the UPC/SKU on each item (identifier) to see if you already have this item in stock. If so, you'd add its contents to the same shelf location (ID) as the existing item. If it’s a new item, you'll find an empty shelf in the correct aisle (resourceType), put a local barcode sticker (ID) on that new shelf, and store it there. You'll cut the strands and replace them with another barcode sticker that points to the item it was tied to (i.e., update the references to the newly stored IDs). In this case, you'll likely convert temporary URIs to permanent IDs when storing the data.

For technical details, see HL7's docs on bundles.

For saving data

Don’t worry about including a resource ID unless your connection specifies that you should include a specific one when writing data to their system.

To handle references between resources, it’s better to use a full URL with the format of urn:uuid:<example-uuid>, where <example-uuid> is a placeholder for a real UUID string.

When you write data back to an EHR system, you should always include whatever data points you have. You can think of this like including a patient’s demographics for a new patient record; the demographics give useful context for the patient’s chart. 

This “demographics” concept is the same for any new “thing” you’re saving to an EHR system. Whenever you send a writeback message, be sure to include any relevant identifiers, codes, or context to tell the EHR system about the data you’re saving, like the following data points: 

  • patient first name
  • patient last name
  • patient date of birth
  • any patient identifiers
  • encounter identifier (if applicable)
  • encounter department/location (if applicable)
  • any unique record identifiers for the triggering event (e.g., order, result, medication admin ID)
  • relevant provider IDs and names (for orders)
  • procedure code (for orders)

Make sure to include the contextual FHIR® resources you reference in your writeback message. For example, if you reference a practitioner in an Encounter resource, also include the Practitioner resource so that the reference works in your connection's system.

Patient identifiers for saving

Work with your connection to understand which patient identifiers will be the most meaningful to them.

For more guidance, review FHIR®’s known identifier systems.

If using an identifier outside the known systems, follow the FHIR® identifier guide by using one of the following:

  • a custom URL, ideally pointing to a web page with information about the identifier system or a NamingSystem resource.
  • a globally unique URN, such as an OID registered to the HL7 OID Registry.
  • the global URI system defined as urn:ietf:rfc:3986 (only if the identifier.value is already a globally unique URI by itself).

Otherwise, leave the system undefined. In this case, you should at least include identifier.type with text and/or coding to give context. Without context, the identifier won’t be useful to the destination’s system.

FHIR® is a registered trademark of Health Level Seven International (HL7) and is used with the permission of HL7. Use of this trademark does not constitute an endorsement of products/services by HL7®.