Consuming FHIR’s Resource Documentation

Developers don’t read the documentation. We think we can work it out on-the-fly.

This is why so many of us have difficulty when we first encounter FHIR. I complain a lot about the FHIR documentation and how difficult it is to find things, but the individual resource pages are surprisingly well structured and well written.

Here’s the full list of R4 resources.

Find the resources your project uses and then dig into the sections outlined below.

I’ll use the Condition resource as an example, but once you understand one resource’s documentation page you’ll be able to navigate all of them.

1. The Resource Content

I often skip the intro section and jump straight into the Resource Content. It’s visual and allows me to see what a resource is composed of — each element listed one after the other.

There’s a lot here, but let’s focus on the 5 sections I’ve highlighted in the screenshot.

a. Modifier Element Flag

This is important. An element with an Is-Modifier flag is an element that cannot safely be ignored.

“Status” and “active” elements usually fall into this category. In the case of Condition, the clinicalStatus and verficiationStatus are Is-Modifier elements.

You would not treat a Condition resource with a clinicalStatus of “inactive” the same as you would one with a clinicalStatus of “active.”

Your code needs to look at all Is-Modifier elements and handle their different values.

b. Cardinality

How many of something there can be. Three different cardinalities are highlighted in the example.

  • 0 .. 1 for code: there can be none and there cannot be more than one
  • 0 .. * for bodySite: there can be none and there can be any number (a list)
  • 1 .. 1 for subject: there must be one and only one (mandatory)

The missing fourth cardinality is:

  • 1 .. *. There must be at least one, and there can be any number (a list). Look at Consent.category as an example.

c. Element Data Type

Most elements in a FHIR resource are of a particular data type. Examples of data types are string, CodeableConcept, DateTime and Identifier.

But some elements can be made up of different data types. In the case of Condition.onset, this element can be any one of:

  • DateTime
  • Age
  • Period
  • String

This can be confusing for developers who write code expecting a DateTime value, only to see that code break a few months later when a perfectly valid Period arrives in a bundle.

The lesson here is that even if your solution always expects a certain data type, it should be robust enough to handle (or ignore) other valid data types.

d. Resource Reference Type

Reference is a data type that connects the current resource to another resource.

What’s significant about these elements in the documentation is that the type column also identifies the precise resource types that can be referenced.

In the case of Condition.recorder, it can only reference a Practitioner, PractitionerRole, Patient or RelatedPerson resource.

Occasionally an element can reference any resource type, in which case the type column with specify “Any” as the allowed type.

e. Terminology Binding

Codes, codings and CodeableConcepts can be bound to specific ValueSets with differing degrees of binding types and strengths.

There are four binding types:

  • Required — you MUST use the specified codes or code system. No exceptions.
  • Extensible — you MUST use the specified codes. BUT, if they don’t apply you can choose not to. (I know, vague!)
  • Preferred — you SHOULD use the specified codes but with a good reason can choose not to.
  • Example — you’re free to choose your own codes or code system.

Condition.bodysite references SNOMED CT as an example, which means you’re free to choose any code system and values that suit your needs.

Condition.clinicalStatus has a required binding to the “Condition Clinical Status Codes” ValueSet. You must pick from this pre-defined list — there’s no leeway.

Always check this column for terminology bindings, as they’re easy to get wrong.

Condition’s “Resource Content.”

2. Search Parameters

I’m often approached by devs asking me to build a custom search parameter so they can search based on a particular element that’s not “based-on” or “subject.”

Often I don’t need to as the search parameter already exists. Its name may not be identical to the name of the element it uses, which is why they didn’t know it existed.

Trial and error is an inefficient way to find a search parameter. Just like the devs I used to work with years ago who failed to construct a simple table fan, these devs didn’t read the documentation.

The bottom of every resource page lists all of the available search parameters for that resource, and clearly defines the type and fhirPath expression that defines them.

Did you know that many elements have more than one search parameter?

Condition.abatement — an element that can be one of five different data types — has three search parameters, each searching on a different data type. Querying on this element may involve using a combination of these three parameters.

Condition’s “Search Parameters.”

3. Extensions

Finding an officially approved extension that meets your needs is a quick and easy win. It’s a satisfying feeling to discover that you don’t have to go through all the effort required to create a new extension.

No running it past the “Data Owner”. No need to add it to your Implementation Guide.

The “Profiles & Extensions” Tab at the top of each resource’s page lists all of the official extensions for a resource. There aren’t many, but where they do exist they tend to fill obvious holes in the resource.

Examples for Condition include condition-outcome and condition-occurredFollowing.

Condition’s “Profiles & Extensions.”

4. Boundaries and Relationships

It doesn’t exist for every resource, but when it does the “Boundaries and Relationships” section is a fantastic source of information on issues you may encounter when using a particular resource.

It also documents the interactions it has with other resources and how they might work together.

I admit to not reading this section often, but every time I do I find that I save time and discover something that I was scratching my head about.

Condition’s “Boundaries & Relationships.”

Finally, don’t forget to read the “Scope & Usage” section at the top of every resource page. I said earlier that I often skip over this section, but I don’t ignore it completely.

It outlines in varying degrees of detail what the resource is for and when you might want to use it — often with examples.

There’s no clearer sign that the FHIR documentation has multiple authors than this important section, as it varies in detail from resource to resource.

Condition’s “Scope & Usage.”

---

Work With Me

Discover more from Darren Devitt

Subscribe now to keep reading and get access to the full archive.

Continue reading