In order to use an extension, there is a three-step process:
Define the extension
Register the extension
Use it in the instance
This page contains examples of how this process executes.
2.1.5.2.1 Patient Consent for Record Sharing
The basic patient resource contains no information relating to patient
consent, and/or the policy under which the patient consents to their registration
details. A social web provider of personal healthcare record (PHR) services
might be obliged to keep track of the particular policy under which
a patient has created their relationship with the PHR provider, and share
this with their participants via their FHIR API. If they wish, they can
extend the patient resource to represent the patient's participation
agreement. Note that other approaches to this problem are possible and preferred, but
this example suffices to demonstrate the extension process.
For the purposes of this example, we assume that the patient agrees to
a participation policy as part of their sign up, and that as the provider
has to change their policy, they ask patients to agree to new participation
details. Each participation agreement has a URI by which it is identified,
and the patient resource will carry this URI for each policy agreement that
the patient has agreed to.
A URI that identifies a participation agreement/policy to which the patient has agreed
Comment
URI is a literal reference to agreement text (html)
Cardinality
1..* (patient cannot participate without at least one agreement)
Type
uri
Invariants
No invariants
is Modifier
No (the participation agreements do not affect that interpretation of the elements of the patient, though they will likely influence how the system interacts with the patient)
Binding
(no binding - not a coded value)
2.1.5.2.1.2 Write the Definition of the Extension
From this table, we can build a formal extension definition. In this case, it looks like this:
<StructureDefinition xmlns="http://hl7.org/fhir">
<url value="http://example.org/fhir/StructureDefinition/participation-agreement"/>
<name value="Example Extension Definition"/>
<!-- snip other metadata -->
<kind value="complex-type"/>
<context>
<type value="element"/>
<expression value="Patient"/>
</context>
<type value="Extension"/>
<baseDefinition value="http://hl7.org/fhir/StructureDefinition/Extension"/>
<derivation value="constraint"/>
<differential>
<element>
<path value="Extension"/>
<short value="Agreed agreement/policy"/>
<definition value="A URI that identifies a participation agreement/policy
to which the patient has agreed"/>
<comment value="URI is a literal reference to agreement text (html).
Systems SHALL conform to the policies as indicated.
For further information, see the partnership agreement..."/>
<mustSupport value="true"/>
<isModifier value="false"/>
</element>
<element>
<path value="Extension.url"/>
<fixedUri value="http://example.org/fhir/StructureDefinition/participation-agreement"/>
</element>
<element>
<path value="Extension.valueUri"/>
<short value="The URI value"/>
<min value="1"/>
<type>
<code value="uri"/>
</type>
<mustSupport value="true"/>
</element>
</differential>
</StructureDefinition>
{
"resourceType" : "StructureDefinition",
"url" : "http://example.org/fhir/StructureDefinition/participation-agreement",
"name" : "Example Extension Definition",
// snip other metadata
"kind" : "complex-type",
"context" : [{
"type" : "element",
"expression" : "Patient"
}],
"type" : "Extension",
"baseDefinition" : "http://hl7.org/fhir/StructureDefinition/Extension",
"derivation" : "constraint",
"differential" : {
"element" : [{
"path" : "Extension",
"short" : "Agreed agreement/policy",
"definition" : "A URI that identifies a participation agreement/policy, to which the patient has agreed",
"comment" : "URI is a literal reference to agreement text (html). Systems SHALL conform to
the policies as indicated. For further information, see the partnership agreement...",
"mustSupport" : "true",
"isModifier" : "false"
}, {
"path" : "Extension.url",
"fixedUri" : "http://example.org/fhir/StructureDefinition/participation-agreement"
}, {
"path" : "Extension.valueUri",
"short" : "The URI value",
"min" : "1",
"type" : [{
"code" : "uri"
}],
"mustSupport" : "true"
}]
}
}
Note that usually one would build the actual profile using a tool. This example was built by hand for this example.
2.1.5.2.1.3 Register the Extension
This means the profile shown above that defines the extension is placed on the web somewhere.
By preference, it will be hosted at a FHIR Profile endpoint, and the best location of all
is the HL7 FHIR Registry .
For this example, we assume that it has been uploaded to the PHR provider's own website at
http://example.org/phr/documents/fhir/extensions.
2.1.5.2.1.4 Use it in the instance
To use the extension in an instance, the extension is placed in the root of the resource, because that was the declared context for the extension.
Note that the URL of the extension refers to the registered location.
The extension definition above simply defines the extension "participation-agreement" and
says that it is used with patient. But the profile above doesn't say that the server
actually uses it. For the PHR provider to indicate that all Patient resources
will use this resource, a StructureDefinition on the patient resource is used:
<StructureDefinition xmlns="http://hl7.org/fhir">
<id value="patient-profile"/>
<!-- snip other metadata, narrative -->
<differential>
<!-- first, the patient root element
- can be copy/paste from the base patient profile -->
<element>
<path value="Patient"/>
<!-- snip definition -->
</element>
<!-- now, the general definition for extensions
- can be copied/pasted from the base patient profile,
with changes for slicing -->
<element>
<path value="Patient.extension"/>
<!-- we're going to slice the extension element, and
one of the extensions is one we have defined -->
<slicing>
<!-- extension is always sliced on url -->
<discriminator>
<type value="value"/>
<path value="url"/>
</discriminator>
<!-- we don't care what the order of any extensions is -->
<ordered value="false"/>
<!-- Other extensions are allowed in addition to this one -->
<rules value="open"/>
</slicing>
<!-- snip definition -->
</element>
<!-- now, the slice that contains our extension -->
<element>
<path value="Patient.extension"/>
<sliceName value="agreement"/>
<!-- clone information from the extension definition.
duplicative, but this duplication makes it simpler overall -->
<short value="Agreed agreement/policy"/>
<definition value="A URI that identifies a participation agreement/policy
to which the patient has agreed"/>
<!-- min has to be 1, since the extension itself has min = 1 -->
<min value="1"/>
<max value="*"/>
<type>
<!-- obviously it has to be an extension -->
<code value="Extension"/>
<!-- and here is the link to the extension definition:
this extension has to conform to the rules laid down in its definition -->
<profile value="http://example.org/phr/documents/fhir/StructureDefinition/participation-agreement"/>
</type>
<isModifier value="false"/>
</element>
<!-- snip the rest of the profile -->
</differential>
</StructureDefinition>
{
"resourceType" : "StructureDefinition",
"id" : "patient-profile",
// snip other metadata, narrative
"differential" : {
"element" : [{
// first, the patient root element
// - can be copy/paste from the base patient profile
"path" : "Patient"
// snip definition
}, {
// now, the general definition for extensions,
// can be copied/pasted from the base patient profile,
// with changes for slicing
"path" : "Patient.extension",
// we're going to slice the extension element, and,
// one of the extensions is one we have defined
"slicing" : {
// extension is always sliced on url
"discriminator" : [{
"type" : "value",
"path" : "url"
}],
// we don't care what the order of any extensions is
"ordered" : "false",
// Other extensions are allowed in addition to this one
"rules" : "open"
}
// snip definition
}, {
// now, the slice that contains our extension
"path" : "Patient.extension",
"sliceName" : "agreement",
// clone information from the extension definition
// duplicative, but this duplication makes it simpler overall
"short" : "Agreed agreement/policy",
"definition" : "A URI that identifies a participation agreement/policy, to which the patient has agreed",
// min has to be 1, since the extension itself has min = 1
"min" : "1",
"max" : "*",
"type" : [{
// obviously it has to be an extension
"code" : "Extension",
// and here is the link to the extension definition:,
// this extension has to conform to the rules laid down in its definition
"profile" : ["http://example.org/phr/documents/fhir/StructureDefinition/participation-agreement"]
}],
"isModifier" : "false"
}]
// snip the rest of the profile
}
}
Note - this step is optional.
2.1.5.2.2 Patient Name Parts
ISO 21090 (Healthcare Datatypes) defines a concept called a "name part qualifier" that contains extra
information about how a particular name part should be used or interpreted. In practice, this field
is used rarely except in particular cultural contexts, where certain part qualifiers are used as a
matter of practice. Following the FHIR design policy, such a field
is not included in the overall definition of the core name datatype, instead is it added as an
extension.
In practice, for cases such as these in ISO 21090, HL7 defines common extensions, and these
are defined either in this specification, or in the FHIR registry .
Not all the codes of the EntityNamePartQualifierR2 are required in this context,
because prefix and suffix are explicitly part of the name types. Rather than
simply refer to the OID for EntityNamePartQualifierR2 (2.16.840.1.113883.5.1122),
in this case we enumerate the available codes, and set the type of the extension to
code. The type of "code" is only allowed if the profile itself defines the codes that
can be used. Here is a table of the codes (see the EntityNamePartQualifierR2 reference for the full definitions):
LS
Legal status
For organizations, a suffix...
AC
Academic
Indicates that a prefix like "D...
NB
Nobility
In Europe and Asia, there are s...
PR
Professional
Primarily in the British Im...
HON
Honorific
An honorific such as 'The Rig...
BR
Birth
A name that a person was given at ...
AD
Acquired
A name part a person acquired. ...
SP
Spouse
The name assumed from the partner...
MID
Middle Name
Indicates that the name par...
CL
Call me
Call me is used to indicate which...
IN
Initial
Indicates that a name part is ju...
This is all then represented formally in a profile. Such profiles do not need to include resource constraint statements; instead, they include just extension declarations
and their associated bindings. In this case, the definition looks like this:
<StructureDefinition xmlns="http://hl7.org/fhir">
<url value="http://hl7.org/fhir/StructureDefinition/iso21090-EN-qualifier"/>
<name value="Iso21090NameQualifier"/>
<title value="iso-21090 Name Qualifier"/>
<!-- snip other metadata, including definition of RIM Mapping -->
<kind value="complex-type"/>
<context>
<type value="element"/>
<expression value="HumanName.given"/>
</context>
<context>
<type value="element"/>
<expression value="HumanName.prefix"/>
</context>
<context>
<type value="element"/>
<expression value="HumanName.family"/>
</context>
<context>
<type value="element"/>
<expression value="HumanName.suffix"/>
</context>
<type value="Extension"/>
<baseDefinition value="http://hl7.org/fhir/StructureDefinition/Extension"/>
<derivation value="constraint"/>
<differential>
<element>
<path value="Extension"/>
<short value="LS | AC | NB | PR | HON | BR | AD | SP | MID | CL | IN"/>
<definition value="A set of codes each of which specifies a certain subcategory
of the name part in addition to the main name part type"/>
<comment value="Used to indicate additional information about the
name part and how it should be used"/>
<mustSupport value="false"/>
<isModifier value="false"/>
</element>
<element>
<path value="Extension.url"/>
<fixedUri value="http://hl7.org/fhir/StructureDefinition/iso21090-EN-qualifier"/>
</element>
<element>
<path value="Extension.value"/>
<short value="LS | AC | NB | PR | HON | BR | AD | SP | MID | CL | IN"/>
<min value="0"/>
<type>
<code value="code"/>
</type>
<binding>
<strength value="required"/>
<description value="A set of codes each of which specifies a certain subcategory
of the name part in addition to the main name part type"/>
<valueSet value="http://hl7.org/fhir/ValueSet/name-part-qualifier"/>
</binding>
<mapping>
<identity value="RIM"/>
<map value="ENXP.qualifier"/>
</mapping>
</element>
</differential>
</StructureDefinition>
{
"resourceType" : "StructureDefinition",
"url" : "http://hl7.org/fhir/StructureDefinition/iso21090-EN-qualifier",
"name" : "Iso21090NameQualifier",
"title" : "iso-21090 Name Qualifier",
// snip other metadata, including definition of RIM Mapping
"kind" : "complex-type",
"context" : [{
"type" : "element",
"expression" : "HumanName.given"
}, {
"type" : "element",
"expression" : "HumanName.prefix"
}, {
"type" : "element",
"expression" : "HumanName.family"
}, {
"type" : "element",
"expression" : "HumanName.suffix"
}],
"type" : "Extension",
"baseDefinition" : "http://hl7.org/fhir/StructureDefinition/Extension",
"derivation" : "constraint",
"differential" : {
"element": [{
"path" : "Extension",
"short" : "LS | AC | NB | PR | HON | BR | AD | SP | MID | CL | IN",
"definition" : "A set of codes each of which specifies a certain subcategory
of the name part in addition to the main name part type",
"comment" : "Used to indicate additional information about the
name part and how it should be used",
"mustSupport" : "false",
"isModifier" : "false"
}, {
"path" : "Extension.url",
"fixedUri" : "http://hl7.org/fhir/StructureDefinition/iso21090-EN-qualifier"
}, {
"path" : "Extension.value",
"short" : "LS | AC | NB | PR | HON | BR | AD | SP | MID | CL | IN",
"min" : "0",
"type" : [{
"code" : "code"
}],
"binding" : {
"strength" : "required",
"description" : "A set of codes each of which specifies a certain subcategory
of the name part in addition to the main name part type",
"valueSet" : "http://hl7.org/fhir/ValueSet/name-part-qualifier"
},
"mapping" : [{
"identity" : "RIM",
"map" : "ENXP.qualifier"
}]
}]
}
}
Note that usually one would build the actual profile using a tool. This example was built from a spreadsheet definition by the FHIR build tooling.
To use the extension in an instance, the extension is nested within the attribute that is extended.
Note that the URL of the extension refers to the registered location.
Defining complex extensions is a little different. They have the same metadata - context, etc. -
but differ in the internal structure. As an example, consider enrolling a patient in a clinical
trial. There are 3 data items to collect:
Code
Name
Cardinality
Type
Content
NCT
Clinical Trial number
1..1
string
The format for the US ClinicalTrials.gov registry number is "NCT" followed by an 8-digit number, e.g.: NCT00000419
period
trialPeriod
0..1
Period
The start and end times of the participation of this patient in the clinical trial
reason
reason enrolled
0..1
CodableConcept
Indication or reason that the patient is part of this trial
NOTE: This extension is included for example purposes only. In most cases, participation in clinical trials would be handled using the ResearchStudy resource, possibly referenced via the workflow-researchstudy extension.
Like simple extensions, the first thing to do is to assign a URI to the
extension, e.g.: http://example.org/fhir/StructureDefinition/patient-clinicalTrial.
Internally, in the extension, the maximum cardinality of the value[x] element is set to 0 since it
will not (and cannot) be used. The Extension.extension element is sliced by URL,
and 3 slices are defined, each with a fixed relative URI which is the code from the table above.
The relevant parts of the definition of this extension are as follows:
<StructureDefinition xmlns="http://hl7.org/fhir">
<id value="patient-profile"/>
<!-- snip other metadata, narrative -->
<differential>
<!-- first, the patient root element
- can be copy/paste from the base patient profile -->
<element>
<path value="Patient"/>
<!-- snip definition -->
</element>
<!-- now, the general definition for extensions
- can be copy/paste from the base patient profile,
with changes for slicing -->
<element>
<path value="Patient.extension"/>
<!-- we're going to slice the extension element, and
one of the extensions is one we have defined -->
<slicing>
<!-- extension is always sliced on url -->
<discriminator>
<type value="value"/>
<path value="url"/>
</discriminator>
<!-- we don't care what the order of any extensions is -->
<ordered value="false"/>
<!-- Other extensions are allowed in addition to this one -->
<rules value="open"/>
</slicing>
<!-- snip definition -->
</element>
<!-- now, the slice that contains our extension -->
<element>
<max value="1"/>
<type>
<!-- obviously it has to be an extension -->
<code value="Extension"/>
<!-- and here is the link to the extension definition:
this extension has to conform to the rules laid down in its definition -->
<profile value="http://example.org/fhir/StructureDefinition/patient-clinicalTrial"/>
</type>
</element>
<!-- snip the rest of the profile -->
</differential>
</StructureDefinition>
{
"resourceType" : "StructureDefinition",
"id" : "patient-profile",
// snip other metadata, narrative
"differential" : {
"element" : [{
// first, the patient root element,
// can be copy/paste from the base patient profile
"path" : "Patient"
// snip definition
}, {
// now, the general definition for extensions,
// can be copy/paste from the base patient profile,
// with changes for slicing
"path" : "Patient.extension",
// we're going to slice the extension element, and,
// one of the extensions is one we have defined
"slicing" : {
// extension is always sliced on url
"discriminator" : [{
"type" : "value",
"path" : "url"
}],
// we don't care what the order of any extensions is
"ordered" : "false",
// Other extensions are allowed in addition to this one
"rules" : "open"
}
// snip definition
}, {
// now, the slice that contains our extension
"max" : "1",
"type" : [{
// obviously it has to be an extension
"code" : "Extension",
// and here is the link to the extension definition:,
// this extension has to conform to the rules laid down in its definition
"profile" : ["http://example.org/fhir/StructureDefinition/patient-clinicalTrial"]
}]
}]
// snip the rest of the profile
}
}
2.1.5.2.4 Modifier Extension: Artifact Status
Some extensions are considered 'modifier' extensions - they alter the meaning or interpretation
of the resource or element containing them as defined the applicable specification. For a more
thorough consideration of the use of modifiers, see Modifier Extensions.
The definition of a modifier artifact is the same as a non-modifier extension except for one flag
on the definition: isModifier = true on the root element.
<StructureDefinition xmlns="http://hl7.org/fhir">
<url value="http://hl7.org/fhir/StructureDefinition/artifact-status"/>
<!-- snip metadata -->
<fhirVersion value="6.0.0"/>
<kind value="complex-type"/>
<abstract value="false"/>
<context>
<type value="element"/>
<expression value="Resource"/>
</context>
<type value="Extension"/>
<baseDefinition value="http://hl7.org/fhir/StructureDefinition/Extension"/>
<derivation value="constraint"/>
<differential>
<element id="Extension">
<path value="Extension"/>
<short value="draft | active | retired | unknown"/>
<definition value="The status of this {{title}}. Enables tracking the life-cycle of the content."/>
<min value="0"/>
<max value="1"/>
<!--
This is the important flag: isModifier = true on the root element.
This makes this extension a modifier extension throughout the FHIR
eco-system.
-->
<isModifier value="true"/>
<isModifierReason value="This is labeled as "Is Modifier" because applications should not use a retired CodeSystem without due consideration"/>
</element>
<element id="Extension.extension">
<path value="Extension.extension"/>
<max value="0"/>
</element>
<element id="Extension.url">
<path value="Extension.url"/>
<fixedUri value="http://hl7.org/fhir/StructureDefinition/artifact-status"/>
</element>
<element id="Extension.value[x]">
<path value="Extension.value[x]"/>
<min value="1"/>
<type>
<code value="code"/>
</type>
<binding>
<!-- snip -->
</element>
</differential>
</StructureDefinition>
{
"resourceType" : "StructureDefinition",
"url" : "http://hl7.org/fhir/StructureDefinition/artifact-status",
// snip various metadata
"fhirVersion" : "6.0.0",
"kind" : "complex-type",
"abstract" : false,
"context" : [{
"type" : "element",
"expression" : "Resource"
}],
"type" : "Extension",
"baseDefinition" : "http://hl7.org/fhir/StructureDefinition/Extension",
"derivation" : "constraint",
"differential" : {
"element" : [
{
"id" : "Extension",
"path" : "Extension",
"short" : "draft | active | retired | unknown",
"definition" : "The status of this {{title}}. Enables tracking the life-cycle of the content.",
"min" : 0,
"max" : "1",
// This is the important flag: isModifier = true on the root element.
// This makes this extension a modifier extension throughout the FHIR eco-system.
"isModifier" : true,
"isModifierReason" : "This is labeled as \"Is Modifier\" because applications should not use a retired CodeSystem without due consideration"
},
{
"id" : "Extension.extension",
"path" : "Extension.extension",
"max" : "0"
},
{
"id" : "Extension.url",
"path" : "Extension.url",
"fixedUri" : "http://hl7.org/fhir/StructureDefinition/artifact-status"
},
{
"id" : "Extension.value[x]",
"path" : "Extension.value[x]",
"min" : 1,
"type" : [
{
"code" : "code"
}
]
// snip
}
]
}
}