Understanding the HL7 v2 message structure
A practical breakdown of how HL7 v2 messages are built — segments, fields, and delimiters — with a worked ADT admission example.
If you work with hospital systems, you will meet HL7 v2 quickly. It is the messaging standard that moves admissions, orders, and results between the applications inside a health system — and despite FHIR's rise, the vast majority of live clinical interfaces still speak v2. This guide breaks down how a v2 message is actually built so you can read one at a glance.
The shape of a message
An HL7 v2 message is plain text. It is a stack of segments, one per line, each separated by a carriage return. Every segment begins with a three-letter code that says what it carries:
MSH|^~\&|SendingApp|SendingFac|ReceivingApp|ReceivingFac|20260803120000||ADT^A01|MSG00001|P|2.5
EVN|A01|20260803120000
PID|1||12345^^^HOSP^MR||DOE^JOHN^A||19700101|M|||123 MAIN ST^^METROPOLIS^NY^10001
PV1|1|I|ICU^101^1
That is a complete (if minimal) ADT^A01 — a patient admission. Four segments: a header, the trigger event, the patient, and the visit.
Segments, fields, and delimiters
Within a segment, data is split into fields by the pipe
character (|). Fields are referenced by position: PID-5
is the fifth field of the PID segment (the patient name). Fields themselves can
be subdivided:
|— field separator^— component separator (e.g. family^given^middle in a name)~— repetition separator (a field that occurs more than once)&— subcomponent separator\— escape character
So DOE^JOHN^A in PID-5 is one field with three
components: family name Doe, given name John, middle initial
A.
Why MSH is special
The MSH (Message Header) segment defines the delimiters for the rest of the message, so it is parsed differently from every other segment:
- MSH-1 is the field separator itself — the
|immediately afterMSH. - MSH-2 is the encoding characters —
^~\&— declaring the component, repetition, escape, and subcomponent characters.
Because of this offset, the field you would count as "the third" is addressed
as MSH-3 (Sending Application) and everything lines up from there.
The header also carries the pieces every interface engine routes on:
- MSH-9 — message type, e.g.
ADT^A01(message codeADT+ trigger eventA01). - MSH-10 — message control ID, the unique handle used in acknowledgements.
- MSH-12 — HL7 version ID, e.g.
2.5.
The segments you will see most
SegmentCarriesMSHMessage header — routing, type, version
EVNThe trigger event and its timestamp
PIDPatient identification — IDs, name, DOB, address
PV1Patient visit — location, attending provider, class
OBRObservation request — the order for a study or test
OBXObservation result — a single result value
Message types worth knowing
- ADT — admit, discharge, transfer (patient demographics and movement).
- ORM / OMG — orders (a request for a study, lab, or procedure).
- ORU — observation results (lab values, report text, and in imaging, study status).
- SIU — scheduling (appointment book, modify, cancel).
Reading a field path
Once you internalize the delimiter hierarchy, any field reference becomes
unambiguous. PID-5.1 is the patient's family name — field 5,
component 1. MSH-9.2 is the trigger event. This is the exact
notation you use when you map a source field to a destination in an integration
workflow, so it is worth getting fluent with.
Where Radinode fits
When you document an interface in Radinode, you are describing exactly these flows — which system sends which message type, and how each field maps across the connection. Capturing the message structure alongside the diagram is what turns a workflow into something a downstream engineer can actually build from.