HL7v2 to FHIR - what you get per message
The FHIR resources produced for ADT, ORU, ORM, SIU, VXU and MDM messages, and the segments each resource comes from.
An HL7v2 message is one flat list of segments, while FHIR splits the same information into separate resources - the patient in PID becomes a Patient, the visit in PV1 an Encounter, each OBX result an Observation. The tables below spell that mapping out, segment by segment and message family by message family.
What a converted bundle contains follows the segments actually present in the message, not a fixed list per message type. Alongside the clinical resources, the sending and receiving facilities from MSH-4 and MSH-6 become Organization resources referenced from the MessageHeader, so every bundle opens with them.
Segments and their resources
| Segment | FHIR resource | Notes |
|---|---|---|
| MSH | MessageHeader | Event coding from MSH-9, source and destination endpoints, focus points at the Patient, the MSH-4 and MSH-6 facilities become Organization resources referenced as sender and receiver |
| PID | Patient | Identifiers, names, birth date, gender, addresses, telecoms, language, marital status, birth place, multiple-birth and deceased indicators |
| PD1 | - | Enriches the Patient - organizations and practitioners become generalPractitioner |
| NK1 | RelatedPerson | One per NK1 - name, relationship, address, telecom |
| PV1 | Encounter | Class, status, locations, attending, referring, consulting and admitting practitioners, service type, admit source, visit number, period |
| PV2 | - | Enriches the Encounter - admit reason becomes reasonCode |
| OBX | Observation | Value typing follows OBX-2, see below |
| AL1 | AllergyIntolerance | One per AL1 - code, category, type, criticality, severity, reactions |
| DG1 | Condition | One per DG1, also appended to Encounter.diagnosis with its use and rank |
| PR1 | Procedure | One per PR1 |
| IN1 | Coverage | One per IN1, plus the payor Organization |
| ORC and OBR | ServiceRequest | One per order group in order and result messages |
| OBR | DiagnosticReport | In result messages, one per OBR, linked basedOn its ServiceRequest |
| NTE | - | Becomes a note on the resource it follows - an Observation, a ServiceRequest or an Appointment |
| SPM | Specimen | One per SPM, appended to the current report's specimen |
| SCH | Appointment | In scheduling messages |
| AIS, AIG, AIL, AIP | - | Enrich the Appointment - service type and participants, with Location and Practitioner resources where applicable |
| RXA | Immunization | In immunization messages - vaccine code, occurrence, dose, performer, lot number, manufacturer Organization |
| RXR | - | Enriches the Immunization - route and site |
| TXA | DocumentReference | In document messages, body gathered from the text OBX segments that follow |
| Z-segments | Basic | Preserved as extensions |
Repeating segments become multiple resources - three NK1 segments produce three RelatedPerson resources, five OBX segments five Observations, and so on.
Practitioner, Location and Organization resources are created on demand when a field references one, e.g. the attending doctor in PV1-7 or the assigned location in PV1-3, and identical entities are deduplicated across the whole bundle.
Message families
The message structure from MSH-9 selects a conversion family, which determines how order-related segments group together:
| Family | Message structures | Adds on top of the common segments |
|---|---|---|
| Admissions and the rest | ADT and everything not listed below | Nothing - the common segments alone |
| Orders | ORM, OML, OMG | ServiceRequest per ORC/OBR group |
| Results | ORU | ServiceRequest and DiagnosticReport per group, with Observations in result and Specimens in specimen |
| Scheduling | SIU | Appointment with participants |
| Immunizations | VXU | Immunization per RXA |
| Documents | MDM | DocumentReference from TXA and the text OBX body |
An ORU^R01 example
from zato.hl7v2 import parse_hl7
raw = (
'MSH|^~\\&|LAB|FACILITY|EHR|FAC|20260315101112||ORU^R01^ORU_R01|CTL002|P|2.9\r'
'PID|||12345^^^HOSP^MR||SMITH^JOHN^A||19800115|M\r'
'ORC|RE|PLACER001|FILLER001\r'
'OBR|1|PLACER001|FILLER001|24331-1^Lipid panel^LN|||202603150930|||||||||||||||||F\r'
'OBX|1|NM|2093-3^Cholesterol^LN||187|mg/dL^^UCUM|<200|N|||F\r'
'NTE|1||Fasting sample\r'
'OBX|2|NM|2085-9^HDL cholesterol^LN||62|mg/dL^^UCUM|>40|N|||F\r'
'OBX|3|NM|2571-8^Triglycerides^LN||145|mg/dL^^UCUM|<150|N|||F\r'
'SPM|1|SPM001||SER^Serum\r'
)
msg = parse_hl7(raw, validate=False)
bundle = msg.to_fhir()
for entry in bundle.entry:
print(entry.resource.resource_type)
Organization
Organization
MessageHeader
Patient
ServiceRequest
DiagnosticReport
Observation
Observation
Observation
Specimen
Each Observation has a valueQuantity - 187, 62 and 145 mg/dL - and the NTE comment is stored in the first one's note. The DiagnosticReport lists all three Observations in result and the Specimen in specimen, and everything points back at the Patient.
Observation values
The OBX-2 value type determines how OBX-5 is represented:
| OBX-2 | FHIR element |
|---|---|
| NM | valueQuantity, with units from OBX-6 |
| ST, TX, FT | valueString |
| CE, CWE, CNE, CF, IS | valueCodeableConcept |
| SN | valueQuantity, valueRange or valueRatio, depending on the structured numeric |
| DT, DTM, TS | valueDateTime |
| TM | valueTime |
A value type outside this table falls back to valueString, so the value stays in the output.
See also
| Page | What it covers |
|---|---|
| Automatic conversion | One call, a complete MLLP-to-FHIR service and validation |
| References and deduplication | How the resources point at each other and identical entities merge |
| Customizing code mappings | Standard tables, local values and unknown codes |
| Z-segments | Custom segments preserved as Basic resources with extensions |
Learn more
Schedule a meaningful demo
Book a demo with an expert who will help you build meaningful systems that match your ambitions
"We evaluated 12 integration platforms and Zato was the only one to score 100%."
Philip Zuñiga, Assistant Professor, University of the Philippines