Handle FHIR identifiers and match patient data

Last updated: Jan 8, 2024
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.

ID vs. identifier

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.

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. As an 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.

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.

There are a couple of 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.

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.

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.

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.

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.