SMART on FHIR resource profiles

To support apps that run unmodified across different health IT systems, we construct a set of “ground rules” that define which data fields are required vs. optional, and which coding systems are used in a given context. The FHIR specification leaves many of these decisions open to downstream implementers, to ensure that FHIR can work with a variety of use cases. But for a viable app platform, we need more.

Working with the community

As much as possible we want to avoid inventing these “ground rules” ourselves. Our aim is to work with the broader community, including the Argonaut Project and the Data Access Framework to converge on a set of profiles that are specific and broadly applicable.

In the meantime, we still have a few constraints of our own that we describe below. These define the data elements and coding systems that are considered essential for a SMART on FHIR implementation. (Eventually we’d like to document these decisions using FHIR’s built-in “profiling” mechanism, but for now we host the following human-readable explanations, along with sample data to demonstrate what we mean.)

Note that these profiles need to be updated to FHIR DSTU2

Why do we need profiles?

Imagine an app that queries a patient’s problem list and wants to create a timeline view of problems in 2014. According to the FHIR specification, an app can query for /Condition?subject=123&onset=2014 to find problems that began in 2014, or it can query for /Condition?subject=123&date-asserted=2014 to find problems that were first detected in 2014.

In practice, any given FHIR server might have data with both onsetDate and dateAsserted or might populate just one of them, or neither (or any mixture of these). This suggests that if you’re building an app for the “general case,” you can’t rely on either field, which makes it hard to build rich, expressive queries. In the worst case, you might query by dateAsserted against a server that only provides onset, and then upon finding no results, might mistakenly conclude that the patient has no problems.

In short: if you get no guarantees about which fields will be populated, you’re limited to just querying for all Conditions and doing all of your filtering work client-side.

Profiles improve the situation by giving you a reliable set of agreed-upon guarantees that go above and beyond FHIR’s base specification.

Patient Demographics

Each Patient must have:

  • 1 or more medical record numbers in Patient.identifier
  • 1 or more names in
  • 1 administrative gender in Patient.gender

Allergy or intolerance

Each AllergyIntolerance must have:

  • 1 sensitivity type (allergy, intolerance, or unknown) in AllergyIntolerance.sensitivityType
  • 1 patient in AllergyIntolerance.subject
  • 1 substance in AllergyIntolerance.substance

The coding system used to record the substance depends on the substance type. There are three cases: drug allergies, drug class allergies, and other.

Allergy to a specific drug

Coded with RxNorm Ingredient codes

Allergies to a specific drug are coded using RxNorm at the ingredient level (using codes with TTY=IN). It is almost certainly an error to claim that a patient is allergic to a specific dose form such as a 100mg tablet of Sulfamethoxazole (rxnorm:402625). Instead, the allergy is captured using the ingredient code for Sulfamethoxazole (rxnorm:10180).


Example: cipro

Allergy to a drug class

Coded with NDF-RT

Allergies to a drug class are captured using NDF-RT. For example, an allergy to Sulfonamide drugs is captured using the drug class code NDFRT:N0000175503


Example: sulfonamides

Food and environmental allergies

Coded with FDA UNII

Allergies to other substances (foods ane environmental allergies) are captured using FDA UNII codes.


Example: shrimp

“No known allergies”

Encoded as List must have:

  • 1 patient in List.subject
  • 1 code value of 52473-6 and system of in List.code
  • 1 date in
  • 1 value of snapshot in List.mode
  • 1 code value of nilknown and system of in List.emptyReason

“No known history of drug allergy”

Encoded as List must have:

  • 1 patient in List.subject
  • 1 code value of 11382-9 and system of in List.code
  • 1 date in
  • 1 value of snapshot in List.mode
  • 1 code value of nilknown and system of in List.emptyReason


Each Immunization must have:

  • 1 patient in Immunization.subject
  • 1 refusal indicator in Immunization.refusalIndicator
  • 1 self-reported indicator in Immunization.reported
  • 1 vaccine code in Immunization.vaccineType

Vaccines coded with CVX

Each immunizations is coded with a vaccineType drawn from CDC’s CVX vocabulary. This is a coding with: System:



Each Condition must have:

  • 1 patient in Condition.subject
  • 1 condition in Condition.code with System of
  • 1 code (confirmed) in Condition.status
  • 1 date in Condition.onsetDate
Example: fever


Each Procedure must have:

  • 1 patient in Procedure.subject
  • 1 procedure in Procedure.type with System of
  • 1 date in
  • 1 date in
Example: mastectomy

Family Member History

Each FamilyMemberHistory must have:

  • 1 patient in FamilyMemberHistory.patient
  • up to 1 height measurement as an valueQuantity extension of url with units of centimeters and system of
  • 1 relationship to patient in FamilyMemberHistory.reation.relationship with system

Smoking Status

Each Smoking Status Observation must have:

  • 1 patient in Observation.subject
  • 1 code value of 72166-2 and system of in Observation.code
  • 1 code with system in Observation.valueCodeableConcept
  • 1 status of final in Observation.status
Example: former smoker

Medication Order (Prescription)

Each MedicationOrder must have:

  • 1 patient in MedicationOrder.patient
  • 1 medicationCodeableConcept or [Medication] ( object in MedicationOrder.medication with system in Medication.code.coding.system
  • 1 object in MedicationOrder.dosageInstruction.timingSchedule with 1 date in event.start and 0 or 1 date in event.end and 0 or 1 objects in repeat (with 1 value in repeat.frequency, 1 value in repeat.units, and 1 value in repeat.duration)
  • 0 or 1 code in MedicationOrder.dosageInstruction.doseQuantity with system of
  • 0 or 1 objects in MedicationOrder.dispense with 1 value in numberOfRepeatsAllowed, 1 code with system of in quantity, and 0 or 1 codes with system of in expectedSupplyDuration

Medication Dispense

Each MedicationDispense must have:

  • 1 patient in MedicationDispense.patient
  • 1 reference to MedicationPrescription in MedicationDispense.authorizingPrescription
  • 1 object in MedicationDispense.daysSupply with an integer number of days
  • 1 medicationCodeableConcept [Medication] ( object in MedicationDispense.dispense.medication with system in Medication.coding.system
  • 1 status of completed in MedicationDispense.dispense.status
  • 1 quantity with system and code of {tablets} and units of tablets in MedicationDispense.dispense.quantity
  • 1 date in MedicationDispense.dispense.whenHandedOver

Vital Signs

A set of Vital Signs is represented usng FHIR Observation resources. Each Observation must have:

  • 1 patient in Observation.subject
  • 1 LOINC-coded Vital Sign (see below) in Observation.code
  • 1 status indicator (see FHIR definitions) in Observation.status
  • 1 quantity with system and a UCUM-coded value (see below) in Observation.valueQuantity
  • 1 date indicating when the value was measured, in Observation.effectiveDateTime

LOINC codes for vital signs

Top-level vital sign codes are all LOINC codes with system of

Vital Sign LOINC Code Units
Height 8302-2 cm, m,[in_us], [in_i]
Weight 3141-9 kg, g, lb_av, [oz_av]
Heart rate 8867-4 {beats}/min
Respiratory rate 9279-1 {breaths}/min
Temperature 8310-5 Cel, [degF]
Body Mass Index 39156-5 kg/m2
Oxygen saturation 2710-2 %{HemoglobinSaturation}
Head circumference 8287-5 cm, m, [in_us], [in_i]
Blood pressure (systolic and diastolic – grouping structure) 55284-4 N/A
Systolic blood pressure 8480-6 mm[Hg]
Diastolic blood pressure 8462-4 mm[Hg]

Grouping blood pressures

The representation of a blood pressure measurement makes systolic/diastolic pairings explicit by using a “grouping observation” with LOINC code 55284-4 (see above). The grouping observation has no value itself, but refers to two individual components for systolic and diastolic values.

Example: blood pressure

Grouping other vital signs

Any time a set of vital signs is measured together, as a set, it can be explicitly grouped using a “grouping” observation with LOINC code 8716-3.

Lab Results

An individual lab result is represented with the FHIR Observation resource. Each result must have:

  • 1 Patient in Observation.subject
  • 1 LOINC code in with system of
  • 1 status indicator (see FHIR definitions) in Observation.status
  • 1 date indicating when the sample was taken (or other “physiologically relevant” time), in Observation.appliesDateTime
  • 1 value (details depend on whether the lab test is quantitative – see below)

Quantitative labs (LOINC scale = Qn)

Lab tests that produce quantitative values include an Observation.valueQuantity element with system and a valid UCUM unit in code.

Example: pCO2 in blood

Non-quantitative labs (LOINC scale = Ord, Nom, or Nar)

Lab tests that do not produce quantitative values include a valueString element containing the non-quantitative value. TODO: describe separate treatment for narrative (with valueString) vs. ordinal (with valueCodeableConcept).

Example: urine appearance
We're hiring a senior developer to work full time on the open source SMART on FHIR project. Learn More!
The SMART on FHIR API is evolving in parallel with the FHIR ballot releases. If you spot problems, please file an issue. Or better yet, you can edit this page.