OBX Segments and Where They End Up in a FHIR Observation

OBX is the segment that carries clinical observations in HL7v2. Every lab result, vital sign, and structured measurement travels through OBX in some system. Mapping OBX to FHIR Observation is one of the most frequent translation tasks and one of the most subtle, because OBX can hold values of many different types and FHIR chooses among them explicitly.

Naming the value routing is the discipline. For related walkthroughs, more FHIR implementation patterns collects the surrounding material.

The Fields That Move the Value

Four OBX fields determine where the observation value lands:

  • OBX-2: value type. NM for numeric, ST for string, CE for coded entry, and so on.
  • OBX-3: observation identifier. The LOINC or vendor-specific code that names the observation.
  • OBX-5: observation value. The actual measurement.
  • OBX-6: units. For numeric measurements.

A pass through the site's HL7 v2 segment → FHIR mapping tool turns an OBX field into a concrete FHIR Observation snippet.

The Value Type Decides the FHIR Slot

OBX-2 (value type) determines which FHIR Observation.value[x] slot the value lands in:

  • NM (numeric) → Observation.valueQuantity.
  • ST (string) → Observation.valueString.
  • CE / CWE (coded entry) → Observation.valueCodeableConcept.
  • TS (timestamp) → Observation.valueDateTime.
  • BIT (boolean) → Observation.valueBoolean.

Getting the routing right requires reading OBX-2 before parsing OBX-5. Parsers that only look at OBX-5 end up guessing the type from the value shape, and the guess is wrong on any string that happens to look numeric.

Units Deserve Their Own Handling

OBX-6 carries units for numeric measurements. FHIR expects units in UCUM format. HL7v2 sometimes carries UCUM units, sometimes carries local codes, sometimes carries free text.

Every integration should validate OBX-6 against UCUM and translate local codes explicitly. Silent acceptance of non-UCUM units passes them through to FHIR and produces resources that terminology validators reject downstream.

The Reference Range Fields

OBX-7 carries the reference range for numeric measurements. FHIR expresses this through Observation.referenceRange. The mapping is direct for simple ranges (like "3.5-5.2") and less direct for age-adjusted or gender-adjusted ranges.

The Interpretation Codes

OBX-8 carries interpretation codes (H for high, L for low, HH for critical high). FHIR maps these to Observation.interpretation with a code from the observation-interpretation value set. The mapping is largely mechanical.

The Sub-ID Groups Related OBX

When multiple OBX segments belong to the same observation (like systolic and diastolic blood pressure), OBX-4 (observation sub-ID) links them. FHIR represents grouped observations through Observation.component (for measurements of the same thing) or Observation.hasMember (for panels).

Choosing between component and hasMember requires judgment. For the pattern-level framing, HL7v2 to FHIR translation patterns worth memorizing covers the recurring case.

The Patient Link

Every OBX is meaningless without a Patient link. The link comes from the enclosing message's PID segment. For the specific PID mapping story, PID vs Patient: what maps and what doesn't covers the identifier translation.

Getting the patient reference right on every Observation is the most-broken thing in first-integration OBX handling. Every Observation should carry Observation.subject pointing at the correct Patient resource.

The Downstream Cost

Wrong OBX mappings produce clinical Observations that decision-support systems act on. The stakes are real. For the message-anatomy framing, reading an HL7v2 message when you only know FHIR covers the wire format around OBX.

Every v2 integration eventually maps OBX. Meeting the routing rules deliberately keeps the mapping honest.

Constructivist-poster diagram of an OBX value type routing graph with red, blue, and grey angular arrows leading from OBX-2 to different FHIR value slot destinations on a warm cream background

Sources