Most labs still send results as HL7 v2 ORU^R01 messages. Most new apps want FHIR. The mapping looks trivial:
OBX|1|NM|2093-3^Cholesterol^LN||212|mg/dL|<200|H|||F|||20261002074500
| OBX field | FHIR R4 Observation |
|---|---|
OBX-3 2093-3^Cholesterol^LN
|
code.coding (LOINC) |
| OBX-5 + OBX-6 | valueQuantity |
OBX-7 <200
|
referenceRange.high |
OBX-8 H
|
interpretation |
OBX-11 F
|
status = final |
| OBX-14 | effectiveDateTime |
The field mapping is the easy 20%. The 80% that breaks production:
-
Time zones.
20261002074500has no offset. FHIR requires one whenever a time is present. Decide the sender's zone explicitly; don't let a library guess. - Local codes. Many labs put their own code in OBX-3. Keep it next to the LOINC code you map to, never drop it.
- Resends. v2 senders retransmit on timeouts. Without a stable identifier per result (report id + code + time + value), your FHIR store fills with duplicates.
-
Corrections. OBX-11
Cmeans corrected. Decide whether a correction updates the earlier Observation (keeping history) or arrives as a new one, and mark the old oneentered-in-errorif so. -
Values that are not numbers.
<5,6,4,positive: parse them deliberately, or store them asvalueStringrather than inventing a number.
All five are cases the lab import of Anpheros (I work on it) has to handle. The full write-up, with a real import response and the FHIR Observation it produced, is here: Lab results API: HL7 v2, FHIR and LOINC.
If you want to check a translated Observation quickly, there is a free FHIR R4 validator that lists every structural error with its path (it does not check terminology; use the official HL7 validator for full conformance).
Top comments (0)