Key FHIR Resources
Resources are the key building blocks of FHIR. A FHIR resource is a structure that contains medical information in an unambiguous format. This allows different systems to understand information in the same way,1 which is necessary for health systems to accurately share data.
1 Core elements
The FHIR core v4.3.0 (also known as Revision 4B, or R4B) defines 140 resources that allow for healthcare interoperability. The HL7® FHIR® standard gives a well-structured summary of FHIR’s core resources:
As shown above, the FHIR core resources are organized into 5 levels:
- Levels 1 and 2 include data types and infrastructure required to implement FHIR, including “meta” FHIR resources used to describe aspects of FHIR itself.
- Levels 3 and 4 include intuitive FHIR resources information such as
Patient
orObservation
. - Level 5 includes abstract FHIR resources such as clinical workflows with the intended use of Clinical Decision Support.
2 Representation
A FHIR resource may be encoded in different standard formats like JSON and XML. These format are used throughout the software industry, not just in healthcare. Using standard formats allows common programming languages and software tools to process FHIR resources.2
JSON looks like this:
{
"resourceType" : "Patient",
"id" : "example",
"name" : [{
"use" : "official",
"family" : "Chalmers",
"given" : ["Peter",
"James"]
}
}
XML looks like this:
<?xml version="1.0" encoding="UTF-8"?>
<Patient xmlns="http://hl7.org/fhir">
<id value="example"/>
<name>
<use value="official"/>
<family value="Chalmers"/>
<given value="Peter"/>
<given value="James"/>
</name>
</Patient>
3 Design
The critical concepts across the FHIR resource design are:
- Granularity: Capture all possible information.
- Flexibility: Work with a variety of pre-existing data pipelines.
- Extensibility: Encompass quirks in real-world workflows.
- Metadata: Support auto-discovery and self-documentation.
FHIR resources support the concepts above and follow object-oriented principles, a key software engineering concept. They bridge the world between technical implementation and real-world medical practice while minimizing compromises.
To understand how FHIR accomplishes this, let’s examine the Patient resource.
4 The Patient resource
Here is a FHIR structure table for the Patient resource:
All FHIR resources have a similar table representing their contents. These tables have the following columns:
- Name: The element name.
- Flags: Special markers that carry information required for implementers. The flags
N
,?!
, andΣ
represent normative, is-modifier, and in-summary respectively. We will not cover FHIR attribute flags in detail here, but HL7 documents them. - Card.: The cardinality of the attribute in format
{minimum}..{maximum}
. Cardinality refers to the number of data points an element can hold. The most intuitive cardinality values are1..1
which means “one value required” and0..1
, which means “one value is optional. However, other options are possible, like0..*
, which means”any number of values.”3 - Type: The primitive or complex data type. A primitive data type is a base data type, like
date
orinteger
. A complex data type is constructed from other data types, like Address. - Description & Constraints: A human-targeted explanation of the element that may contain constraints that implementers must enforce. Constraints (like “element X must be populated if element Y is missing”) may be formally defined through a language called FHIRPath.
Defining a FHIR resource automatically generates a structure table, so structure tables are available for any resource.
4.1 Basic types example: Patient.active
Under “Patient” there is an element active
which is referred to as Patient.active
. From the table we know that Patient.active
is a boolean
(i.e., “true” or “false”) and can either be omitted or have one value (cardinality 0..1
).
An example of the Patient.active
element in JSON format would look like:
{
...
"active": "true",
...
}
And in XML:
...active value="true"/>
< ...
4.2 Complex types example: Patient.name
Patient.name
is of complex type HumanName. Complex types are FHIR resources and have their own structure table. Here’s the one for HumanName:
HumanName’s elements all have primitive types, such as HumanName.given
, an array of zero or more strings, and HumanName.use
, a code-string that must be one of the provided values. As an example, the name Pieter van de Heuvel would be represented in JSON as:
{
"name": [
{
"use": "usual",
"family": "van de Heuvel",
"given": [
"Pieter"
],
"suffix": [
"MSc"
]
}
]
}
The structure of HumanName highlights the flexibility of FHIR’s approach to modeling data. HumanName
allocates seven separate elements to represent a person’s name. Compare this with a standard approach in a relational database, which would typically allocate only a few fields.
In FHIR, all of these elements are, allowing for flexibility in how implementers represent names. For example, some implementers might store names as a single string (e.g., Pieter van de Heuvel, MSc
), while others might split up the name parts into separate elements (like the JSON above).
Making elements optional balances flexibility with interoperability: this approach provides a standard location and encoding for the data element in question, without requiring all systems to populate it. This approach is used throughout the core FHIR resource definitions.
This degree of flexibility is not helpful in all use cases. FHIR addresses this through resource Profiles, which provide a way to computably describe use case-specific constraints (e.g., “all names must include a family
element”). Profiles are collected in Implementation Guides (IGs) to provide a complete specification based on FHIR for a given use case.
4.3 Choice elements example: Patient.deceased[x]
Elements that can have more than one data type are called choice elements. The Patient.deceased[x]
attribute demonstrates some characteristics of a choice element.
The term
Patient.deceased[x]
, with[x]
in the name, appears in documentation only–never in an instance of Patient that’s been populated with data.Instead, one and only one of the following may appear in an instance of Patient:
Patient.deceasedBoolean
orPatient.deceasedDateTime
. The documentation shows that these are the two valid types forPatient.deceased[x]
.All choice elements must have a maximum cardinality of
1
per the FHIR specification.Patient.deceased[x]
happens to have a minimum cardinality of0
, so an instance of Patient may also omit bothPatient.deceasedBoolean
andPatient.deceasedDateTime
. Other choice elements may have a minimum cardinality of1
and require one of the indicated datatypes.
This flexibility allows the status of non-deceased patients to be represented by Patient.deceasedBoolean = false
or an absent value, while deceased patients can be represented by Patient.deceasedBoolean = true
or Patient.deceasedDateTime = "2023-01-01T01:01:01"
.
Choice elements are always denoted by a [x]
suffix in documentation. The [x]
is replaced with the name of the datatype in CamelCase: deceased[x]
becomes deceasedDateTime
for the dateTime type.
While choice elements provide flexibility, they add complexity for implementers, including researchers. When working with choice elements, consider the following:
Assume that any of a choice element’s possible types may be present. For example, a tabular representation of Patient instances would include two columns related to “deceased”:
deceased_boolean
anddeceased_datetime
. An analyst could add logic to collapse this down to a single column for a given analysis (e.g., logic like, “ifdeceased_datetime
is not empty anddeceased_boolean
is missing, then setdeceased_boolean
totrue
”).When possible, use existing software libraries to do the FHIR-to-tabular conversion, such as R’s fhircrackr, which may simplify handling choice elements.
When developing custom software, use FHIR’s official list of choice elements to systematically handle them rather than hard-coding special cases for each resource.
If possible, use FHIR profiles to add constraints to disallow undesirable datatypes for choice elements. For example, if
Patient.deceasedDateTime
is never useful for a given use case, a profile of Patient could disallowPatient.deceasedDateTime
and requirePatient.deceasedBoolean
. This is like defining a data dictionary ahead of data collection and can drastically simplify analysis as long as the data sources also implement the custom profiles.
4.4 CodeableConcepts example: Patient.maritalStatus
Patient.maritalStatus
is a CodeableConcept, which is a commonly used complex type in FHIR. CodeableConcepts bind an attribute to a specific set of terminology concepts. Patient.maritalStatus
is bound to the Marital Status Codes Value Set. For more on FHIR’s terminology resources, see the terminology module.
In addition to identifying a value set for the binding, a CodeableConcept also identifies the strength of the binding:
required
binding: The value of the element must be from the specified value set.extensible
binding: If a code in the specified value set represents the concept, then that code must be used. Otherwise, a different code can be used.preferred
binding: The use of codes from the specified value set is encouraged but not required.example
binding: The specified value set is an example, and codes outside the specified value set can be used freely.
The base FHIR specification generally does not have required
bindings as these restrict the flexibility of resources. Instead, required bindings are added for specific use cases via FHIR profiles.
Implementers and researchers should consider the following when implementing CodeableConcepts:
Using a FHIR profile to require specific value sets simplifies analysis.
Unless an element has a
required
binding, do not assume that FHIR data will only include codes from the specified value set. Make sure you perform an exploratory data analysis for any CodeableConcept binding strength other thanrequired
.For example, the
Patient.maritalStatus
binding isextensible
: while you may see values from the bound value set (likeM
for married), you may also see values from other value sets (like the SNOMED CT concept 54986009 “Engaged to be married (finding)” ).
4.5 Inheritance in FHIR
In software engineering, inheritance is a common pattern for sharing attributes across similar classes (e.g., a parent class called “pet” might have two child classes called “dog” and “cat”. “Dog” and “cat” inherit properties from the “pet” parent class, like “name,” “weight,” and “cuteness.”).
FHIR has a similar pattern, where resources like Patient inherit from a parent type called DomainResource. You can see this in the first row of the structure table for Patient:
Similarly, DomainResource is a child of Resource, which is the base of almost all FHIR resources. Because FHIR resources are children of DomainResource, they have the same set of core elements in their computable representation. This is useful if you are writing software that needs to process resource definitions from the FHIR specification.
FHIR profiles also exhibit inheritance, where a profile inherits the constraints from another profile or from a base FHIR resource.
4.6 A Patient Example
To summarize the Patient resource, here is an anonymized example from the real world:
{
"resourceType": "Patient",
"id": "f001",
"text": {
"status": "generated",
"div": "..."
},
"identifier": [
{
"use": "usual",
"system": "urn:oid:2.16.840.1.113883.2.4.6.3",
"value": "738472983"
},
{
"use": "usual",
"system": "urn:oid:2.16.840.1.113883.2.4.6.3"
}
],
"active": true,
"name": [
{
"use": "usual",
"family": "van de Heuvel",
"given": [
"Pieter"
],
"suffix": [
"MSc"
]
}
],
"telecom": [
{
"system": "phone",
"value": "0648352638",
"use": "mobile"
},
{
"system": "email",
"value": "p.heuvel@gmail.com",
"use": "home"
}
],
"gender": "male",
"birthDate": "1944-11-17",
"deceasedBoolean": false,
"address": [
{
"use": "home",
"line": [
"Van Egmondkade 23"
],
"city": "Amsterdam",
"postalCode": "1024 RJ",
"country": "NLD"
}
],
"maritalStatus": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus",
"code": "M",
"display": "Married"
}
],
"text": "Getrouwd"
},
"multipleBirthBoolean": true,
"contact": [
{
"relationship": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v2-0131",
"code": "C"
}
]
}
],
"name": {
"use": "usual",
"family": "Abels",
"given": [
"Sarah"
]
},
"telecom": [
{
"system": "phone",
"value": "0690383372",
"use": "mobile"
}
]
}
],
"communication": [
{
"language": {
"coding": [
{
"system": "urn:ietf:bcp:47",
"code": "nl",
"display": "Dutch"
}
],
"text": "Nederlands"
},
"preferred": true
}
],
"managingOrganization": {
"reference": "Organization/f001",
"display": "Burgers University Medical Centre"
}
}
Note that JSON representations of resources begin with resourceType: "<resource>"
to indicate the base FHIR resource type.
In XML representations of resources, the tag enclosing the data identifies the resource type (in this case, <Patient ...> ... </Patient>
).
Typically, JSON is easier to read (both for humans and computers) than XML, so JSON is used primarily in FHIR for Research.
Regarding the JSON and XML representations of FHIR, implementers and researchers should be aware of the following:
In either JSON or XML, the underlying data of the FHIR resource are the same. You can convert between JSON and XML representations of FHIR data without loss of information.
You should use JSON by default when writing code to ingest in FHIR instances (or computable representations of FHIR profiles or resource definitions).
When requesting FHIR data from a server, you can specify the format of the response.
If you work with R, the fhircrackr library uses the XML representation of FHIR resource instances. If you use this library, you will need basic familiarity with XML to extract data elements from the FHIR resource instances.
5 The Observation resource
Observation is another commonly used FHIR resource. It captures vital signs, laboratory data, imaging results, clinical findings, device measurements, and more. Like the Patient resource, there is an Observation structure table:
Below is a JSON example Observation
of high blood glucose levels:
{
"resourceType": "Observation",
"id": "f001",
"text": {
"status": "generated",
"div": "..."
},
"identifier": [
{
"use": "official",
"system": "http://www.bmc.nl/zorgportal/identifiers/observations",
"value": "6323"
}
],
"status": "final",
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "15074-8",
"display": "Glucose [Moles/volume] in Blood"
}
]
},
"subject": {
"reference": "Patient/f001",
"display": "P. van de Heuvel"
},
"effectivePeriod": {
"start": "2013-04-02T09:30:10+01:00"
},
"issued": "2013-04-03T15:30:10+01:00",
"performer": [
{
"reference": "Practitioner/f005",
"display": "A. Langeveld"
}
],
"valueQuantity": {
"value": 6.3,
"unit": "mmol/l",
"system": "http://unitsofmeasure.org",
"code": "mmol/L"
},
"interpretation": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation",
"code": "H",
"display": "High"
}
]
}
],
"referenceRange": [
{
"low": {
"value": 3.1,
"unit": "mmol/l",
"system": "http://unitsofmeasure.org",
"code": "mmol/L"
},
"high": {
"value": 6.2,
"unit": "mmol/l",
"system": "http://unitsofmeasure.org",
"code": "mmol/L"
}
}
]
}
By observing that the resourceType
is "Observation"
and using the structure table above, you can interpret the JSON content as follows:
Observation.id = f001
: Theid
attribute from the grandparent classResource
. See accessing FHIR data for how to use a resource id.Observation.text
: Human-targeted text in HTML that an EHR will display if FHIR software fails.Observation.status = final
: A required code string. This indicates the observation is finalized.Observation.code
: A requiredCodeableConcept
, using LOINC for the example binding.Observation.subject
: A Reference to another FHIR resource. In this case, it is the example Patient from earlier.Observation.valueQuantity
: A suppliedvalue[x]
choice element for storing the result of the test. In this case, they use type Quantity to specify blood glucose concentration.
6 The Bundle resource
Grouping multiple FHIR instances into one package is often helpful, like grouping the blood-glucose Observation example above with the referenced Patient. The Bundle resource is often used for this in FHIR.
In an instance of Bundle, each grouped instance is stored inside Bundle.entry[i].resource
. Find examples of Bundles here.
You may discover certain FHIR communities using NDJSON (Newline-Delimited JSON) instead of Bundle
. In NDJSON, each FHIR resource is printed on one line, and a new line indicates the next FHIR resource. NDJSON is more efficient than Bundle
for large data transfers, and, as of March 1st 2023, FHIR R5 includes NDJSON in Draft status. FHIR data in NDJSON will likely be relatively rare for the next few years as implementers catch up. Bundle
is used more frequently, and can include pagination for large amounts of data.
7 The CapabilityStatement resource
A CapabilityStatement is a resource that contains metadata about a FHIR server, including what resources the server hosts and how to access them.
CapabilityStatements provide information like:
CapabilityStatement.url
: The base URI for the FHIR server. This may also be the URI for capability statement itself, which includes the base URI for the server.CapabilityStatement.fhirVersion
: The FHIR version that the API conforms to. Note that a FHIR server may provide API endpoints for multiple FHIR versions simultaneously via API endpoint URLs likehttps://fhir.example.com/R4/...
andhttps://fhir.example.com/R5/...
for FHIR R4 and R5 respectively.CapabilityStatement.format
: The encoding formats supported by the FHIR server. FHIR queries must specify one of these formats via the HTTPAccept
Header.CapabilityStatement.implementationGuide
: The implementation guides (IG) that the FHIR server conforms to. However, a server may be partially or fully compliant to an IG without listing it in the metadata.CapabilityStatement.rest[i].security.service
: The RESTful security services required to access data on this server. This example uses SMART-on-FHIR, but other possibilities include OAuth or UDAP.CapabilityStatement.rest[i].resource.type
: All FHIR resources supported by the server. Note: this does not include foundational resources such asCapabilityStatement
orBundle
, but typically resources level 3 and higher.CapabilityStatement.rest[i].resource.interaction
: The RESTful interactions available for that resource by the server. For example, thesearch
interaction is a RESTful API action available in FHIR. TheCapabilityStatement.rest[i].resource.searchParam
field specifies what search parameters are possible.
Properly implemented FHIR servers must provide an instance of CapabilityStatement at the /metadata
endpoint.4 This provides a way for software to discover key information about the features of a given FHIR server. Note that the real-world capabilities of a FHIR server may not match its stated capabilities, so software that accesses FHIR servers should be resilient to deviations from the published CapabilityStatements.
8 Other common FHIR resources:
- Condition
-
A problem, diagnosis, or clinical event. It should be the reason for a medical intervention and tie into a larger clinical workflow. There is some use-case overlap with
Observation
; an IG will provide better guidance. - Procedure
-
A medical activity performed on a patient, such as surgery, diagnostic procedures, or therapy. It should be a part of a clinical workflow.
- Practitioner
-
Any individual providing healthcare or a related service, from physicians to receptionists to service animals.
- Organization
-
Any formal or informal group of entities acting towards a collective cause, such as hospitals, departments, corporations, or health insurance groups.
- Composition
-
A set of FHIR resources that create a single coherent clinical statement, and usually acts as the skeleton for a document. This is often used in conjunction with a
Bundle
. - Extension
-
A FHIR resource composed of a definitive URL and an
Extension.value[x]
of any type. Almost all resources inherit an extension attribute fromDomainResource.extension
, and an IG should explain how to use it. - StructureDefinition
-
A FHIR resource that defines other FHIR resources. A structure definition instance exists for all FHIR resources, which allows for powerful dynamic programming and automated documentation.
- OperationDefinition
-
A FHIR resource that defines FHIR operations in addition to traditional REST operations. OperationDefinitions often begin with a dollar sign (
$
). For example,https://fhir.example.com/Patient/$match
will perform a patient matching operation. This resource allows for powerful dynamic programming for FHIR operations.
Footnotes
When systems exchange information with unambiguous and shared meaning, it is called semantic interoperability.↩︎
In contrast, HL7 V2 messages use their own proprietary encoding format, which cannot be parsed without a purpose-built software or custom code.↩︎
A cardinality of
0..*
might be appropriate for a “middle name” element, where a person might have no middle name, one middle name, or multiple middle names.↩︎http://hapi.fhir.org/baseR4/metadata is a real-world example of a CapabilityStatement instance.↩︎