All docs
HL7

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.

Understanding the HL7 v2 message structure

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 after MSH.
  • 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 code ADT + trigger event A01).
  • 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

SegmentCarries MSHMessage 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.

Understanding the HL7 v2 message structure — Radinode Docs