In this module you will learn more about Extensions. We will use Forge, the official HL7®FHIR® profile editor, to edit our profiles. You can download Forge here.

The topics covered in this module are:

  • The use of extensions
  • Guidelines for adding extensions
  • Types of extensions
  • Extensions in Forge

Reading material

1. The use of extensions

It is common for specific implementations to have valid requirements that are not part of the core FHIR Specification. Incorporating all valid requirements would make the FHIR spec very cumbersome and difficult to implement. Instead, the specification expects that such additional requirements will be implemented as extensions.

Extensions are a way to extend an element or resource to include additional elements not present in the original, e.g. adding a birth place in addition to the date on the Patient resource. At first glance this appears to conflict with the concept of constraining resources as you are adding an element to the resource. However, in FHIR all resources and elements have the option to be extended by default unless someone specified otherwise.

Extensions are created using the StructureDefinition resource, the same building block used for resources and profiles. At the bare minimum the extension must be given a canonical url to be able to idenitify it (e.g. http://hl7.org/fhir/StructureDefinition/birthPlace) and the data type of the elements value must be specified (in this case a string). You should also fill in the definition and purpose as good practice to allow for easy re-use of extensions.

After you've made your extension, you can plug it into your profile for use. In section 4 below we'll show how to define and add extensions using Forge.

2. Types of extensions

2.1 Modifier extensions

If an extension significantly modifies the clinical meaning of a resource - meaning that not understanding it is not an option - it shall be marked with isModifier. The reason is for clinical safety: if a system doesn't understand a normal extension in a resource, it may still process it - but not if the extension is a modifier one. If it is a modifier, the system must know the meaning of the extension before it can process it, and this, for example, allows you to use extensions that negate the meaning of a value safely.

Here is what the FHIR spec has to say about this:

  • Applications SHALL always check for modifier extensions when processing the data from any element that can carry one
  • If a Modifier Extension that an application does not understand is present, the application SHALL refuse to process the resource or affected element, or SHALL provide an appropriate warning to its users

2.2 Complex extensions

An extension that adds more than one value is called complex extension, as it's defined by a tree of nested extensions. As an example, consider extending a patient with an opt-in status for a clinical trial containing three fields: clinical trial number, period of involvement and a reason for enrollment.

  <extension url="http://hl7.org/fhir/StructureDefinition/patient-clinicalTrial" >
    <extension url="NCT" >
      <valueString value="123456789" />
    <extension url="period" >
        <start value="2009-03-14" />
    <extension url="reason" >
          <system value="http://acme.org/codes/general" />
          <code value="tt14j" />
  <!-- other data for patient -->

3. Guidelines for using extensions

3.1 When using extended resources

If you choose to use extensions there are a number of guidelines that must be followed:

  • When sending resources that use extensions, make sure the extensions are defined and published (i.e. on simplifier.net or elsewhere).
  • When reading, navigating through or searching resources, check whether there are any modifier extensions and make sure your system understands them. If it does not, abort the operation.
  • If there are non-modifier extensions and you do not understand them, you may skip them.

3.2 Defining extensions and extending resources

  • Reuse extensions whenever you can. When using extensions, first consult the HL7 FHIR registry, FHIR in-spec registry, or Simplifier.net to find extensions that are already defined and may be suitable for your project.
  • Once you have checked HL7 and Simplifier for available extensions, you can either add an extension that you have found or create your own extension that may fit your use case better then anything available. It is best to reuse existing material as much as possible. This increases the likelihood of interoperability. For example, say you want to extend your Patient profile with the place of birth -an extension for Place of Birth for a Patient can be found in the in-spec registry.

4. Creating an extension in Forge

If you cannot find a predefined extension, you can build your own. In Forge, go to “New” and click “New Extension” (or Ctrl + E) to create a new extension, where the “Element Tree” section will be open by default. In the Properties section, you can provide context information, a canonical URL, name and other relevant information.

4.1 Context information

When you build a new extension in Forge, Forge will automatically show warning messages in the lower section of your screen highlighting the need to provide context information for this new extension. You can provide this information in “Properties” tab of the extension.

Context Type indicates if the extension extends a resource, data type, mapping, or another extension and it must be filled in. You can then give the exact context by pressing the + symbol after Context. This brings you to a new screen were you can select the specific resource or datatype where the extension needs to be placed. If you extend at the resource level you can click “Select Resource”. If you extend at the element level first select that element and then click “Select Element”. Depending on where the extension will be used, you can add more context information.

4.2 Value[X]

A new extension starts with one element containing a “Value[X]”. A “Value[X]” can contain all datatypes, most likely this needs to be constrained to a more specific datatype. In Forge, this can be done in the Element Properties tab by selecting only the wanted datatypes.

4.3 Complex extensions

In Forge, elements can be added and removed from the extension profile with the use of the Add and Remove buttons. When adding an element, it will be placed at a level lower than the selected element. Internally, in the selected (parent) element, the cardinality of the value[x] element will be set to 0 since it will not (and cannot) be used. The Extension.extension element is sliced by URL, and each slice is defined with a fixed relative URI.

5. Adding an extension to your profile

In Forge, you can connect your extension to your profile when you have it opened in your session explorer. Select the element in the Element Tree of your profile where you want to add the extension. Then, click the paperclip icon with the name “Extend” which is shown in the tool section above the element tree. If you are extending the profile then position your cursor on the backbone element and then click extend. Forge shows a warning highlighting that the extension element is empty and it should be associated with an extension definition. This is done by selecting the newly made extension element and click the dropdown menu in the Element Properties section under Extension. All of the defined extensions in your session explorer will be available. Click the desired extension definition. It is also possible to provide extension's canonical URL here if you do not have the extension available in Forge.

Real-life examples

Here below are examples of customers that we helped building profiles.

Stichting Koppeltaal

Stichting Koppeltaal is a Dutch organization that enables FHIR-based exchange of data between e-health applications in the care sector. The example below shows the KoppeltaalPatient profile, which is derived from the nl-core-patient profile.

This profile has the following extensions:

  • preferredPharmacy (derived from the base profile nl-core-patient)
  • nationality (derived from the base profile nl-core-patient)
  • person-age (added in the KoppeltaalPatient profile)
url1..1uriFixed Value
useΣ ?!0..1codeBinding
url1..1uriFixed Value
url1..1uriFixed Value
url1..1uriFixed Value
url1..1uriFixed Value
useΣ ?!0..1codeBinding
systemΣ1..1uriFixed Value
activeΣ ?!0..1boolean
url1..1uriFixed Value
useΣ ?!0..1codeBinding
url1..1uriFixed Value
url1..1uriFixed Value
url1..1uriFixed Value
useΣ ?!0..1codeBinding
useΣ ?!0..1codeBinding
useΣ ?!0..1codeBinding


HelseVest is a Norwegian health authority, responsible for the western region of Norway.

HelseVest Perioperative

The HelseVest Perioperative project aims to provide integrations covering the perioperative domain. Below is an example of a complex extension that was built for this project. This extension is used in the HelseVestProcedure profile for the registration of timestamps during a procedure (e.g. time of first cut or start of surgery). To make the extension as generic and reusable as possible, instead of building an extension for each type of timestamp, the type is specified in the extension itself by adding the following "child" extensions:

  • TimeType: the type of timestamp, e.g. time of start aneasthesia
  • StartDateTime: the actual timestamp
  • Comment: an optional text field for additional comments


url1..1uriFixed Value
url1..1uriFixed Value
url1..1uriFixed Value
url1..1uriFixed Value


Below you can see the HelseVestProcedure profile that uses this extension.


definitionΣ0..*Reference(PlanDefinition | ActivityDefinition | HealthcareService)
partOfΣ0..*Reference(Procedure | Observation | MedicationAdministration)
statusΣ ?!1..1codeBinding
notDoneΣ ?!0..1boolean
contextΣ0..1Reference(Encounter | EpisodeOfCare)
actorΣ1..1Reference(Practitioner | Organization | Patient | RelatedPerson | Device)
reasonReferenceΣ0..*Reference(Condition | Observation)
usedReference0..*Reference(Device | Medication | Substance)


HelseVest Prescription

The Helsevest Prescription project aims to provide integrations for medication prescription. The example below shows the MedicationStatement profile that was built for this project. It contains two extensions at the base profile level and a couple of extensions on the underlying elements. The prescriptionStatus extension on the status is an example of a Modifier extension as it changes the meaning of the element. Receiving systems should prioritise prescriptionStatus over status if it is present. When the prescriptionStatus is set to 'on-hold', MedicationStatement.status should be set to 'intended'.

NameFlagsCard.TypeDescription & Constraintsdoco
.. MedicationStatement IKULE Prescribing profile.
kuleprescribing-5: Reason not taken must be filled if wasNotTaken is true
... authoredOn S1..1ExtensionURL: http://nictiz.nl/fhir/StructureDefinition/mp9-authored-on
... drugUseType S..1ExtensionURL: http://hl7.no/fhir/StructureDefinition/kule-drug-use-type
Binding: Legemiddelbruk (required)
... identifier Slice: Unordered, Open, by system
... identifier (prescriptionInstance) S1..1Prescription identifier
.... use Fixed Value: official
.... system Fixed Value: urn:oid:2.16.578.
... identifier (LIB) ..1
.... use Fixed Value: secondary
.... system Fixed Value: urn:oid:OID-FOR-LIBS-HERE.
... identifier (eResept) ..1
.... use Fixed Value: secondary
.... system Fixed Value: urn:oid:OID-FOR-ERESEPT-HERE.
... informationSource SReference(Patient | PractitionerNorway | RelatedPerson)
... status S
.... prescriptionStatus S..1ExtensionURL: http://hl7.no/fhir/StructureDefinition/kule-prescription-status
..... valueCode Binding: (unbound) (required)
... wasNotTaken S
... reasonNotTaken S
... reasonForUse[x] SBinding: Bruksområde til etikett (required)
... effectivePeriod SPeriod
.... start 1..
.... end
... medicationReference SReference(KULE Medication)
... dosage Ikuleprescribing-1: Dosage must include a freetext if no structured dosage is used
kuleprescribing-3: Either detailed timing information or coded dosage information can be specified, but not both
kuleprescribing-4: daysNotAdministeredAmount must always be used in combination with daysAdministeredAmount
.... calculationBasis S1..1ExtensionURL: http://hl7.no/fhir/StructureDefinition/kule-calculation-basis
..... valueCode Binding: (unbound) (required)
.... daysAdministeredAmount S..1ExtensionURL: http://hl7.no/fhir/StructureDefinition/kule-days-administered-amount
.... daysNotAdministeredAmount S..1ExtensionURL: http://hl7.no/fhir/StructureDefinition/kule-days-not-administered-amount
.... shortDosage S..1ExtensionDosage timing information expressed as a code
URL: http://hl7.no/fhir/StructureDefinition/kule-short-dosage
Binding: Coded dosage timing (required)
.... text S
.... timing
..... administerAtSpecificTime S1..1ExtensionURL: http://hl7.no/fhir/StructureDefinition/kule-timing-exact
..... extension SExtensionURL: http://hl7.no/fhir/StructureDefinition/kule-timing-interval
Binding: Benevning tidsenhet (required)
..... repeat Ikuleprescribing-2: Either specificTime or timePeriod can be specified, but not both
...... specificTime S..1ExtensionURL: http://hl7.no/fhir/StructureDefinition/kule-time-of-day
...... timePeriod S..1ExtensionURL: http://hl7.no/fhir/StructureDefinition/kule-timeperiod
...... dayOfWeek SExtensionURL: http://nictiz.nl/fhir/StructureDefinition/mp9-day-of-week
Binding: http://decor.nictiz.nl/fhir/ValueSet/2.16.840.1.113883. (required)
.... asNeeded[x] ..0
.... site[x] S
.... route S
..... coding Binding: Administrasjonsvei (required)
..... text ..0
.... quantityQuantity (SimpleQuantity) SSimpleQuantityBinding: Enhet for dosering (required)
.... rate[x] SSlice: Unordered, Open, by @type
.... rate[x] (ratio) SRatio
..... numerator Binding: Måleenhet for legemidlers styrke (required)
..... denominator Binding: Benevning tidsenhet (required)
.... rate[x] (range) SRange
..... low (SimpleQuantity) Binding: Måleenhet for legemidlers styrke (required)
..... high (SimpleQuantity) Binding: Måleenhet for legemidlers styrke (required)

doco Documentation for this format


In this exercise you will continue with the Patient profile that you created in the Start Profiling module. If you did not follow this module, please create a new profile on Patient and complete the required fields in the Properties tab. Start by reading the case description. Here below are a couple of links that you may find useful during this exercise:

    Case description
    Hospital X wants to receive patient data from general practitioners. The hospital has decided to build conform the FHIR standard, starting with administrative data of patients and their general practitioner. The following (additional) requirements are specified:
  • Place of birth is mandatory
  • Optional opt-in for one or more clinical studies

Steps to follow

1. Simple extension

  1. Visit Simplifier.net and the FHIR specification and search for a relevant extension for place of birth.
  2. Found one? Download the XML and open it in Forge.
  3. Or build your own extension in Forge...
  4. Add the extension to your profile and make it mandatory.

2. Complex extension

  1. Build a new extension in Forge for opt-in status.
  2. Add three elements: clinical trial number (String), period of involvement (Period) and reason for enrollment (CodeableConcept).
  3. For CodeableConcept you may use a fictive naming system.
  4. Add the extension to your profile.


We are always looking for ways to improve our products. The Profiling Academy was built using our own IG-editor in Simplifier. If you have any feedback on this module or on our Profiling Academy in general, please leave a comment in the Issue Tracker of the project.

Get in touch

Start profiling

Most modules end with an exercise. Use Forge to start profiling yourself. Just contact us at simplifier@fire.ly if you need any help.

Learn more

Follow one of our predefined or tailor-made courses. We will make sure you know FHIR inside-out.

Need help or advice?

Let us assist you with your FHIR use case. Visit our company website to know more about our services or get into contact with Rien Wertheim right away.