MSH: Message header
Before you open a letter you look at the envelope: who sent it, who it is for, when it was posted, and what kind of post it is. MSH is that envelope. It carries nothing about the patient; it tells the receiving system what has arrived and how to read the rest.
MSH is the first line of every HL7 v2 message. It sets the delimiters the rest of the message uses. It also names the sender, the receiver, the time and the kind of message.
The shape of one line
required empty in this messageevery box is one | apart
Where MSH appears
| Message | Segment order |
|---|---|
| Every message | MSH is always first, and always exactly once |
| ADT^A01 admit | MSH → EVN → PID → [PD1] → PV1 |
| ACK acknowledgment | MSH → MSA → [ERR] |
| Batch | FHS → {BHS → {MSH …} → BTS} → FTS |
MSH appears in 187 of the 202 message structures the standard defines.
A whole message
MSH|^~\&|LABSYS|STJOSEPH|EPIC|STJOSEPH|20240314141207||ORU^R01^ORU_R01|LR20240314-88412|P|2.5.1|||AL|NE|USA|ASCII|en PID|1||1000345678^^^STJOSEPH^MR||CARTWRIGHT^ELEANOR^MAY^^^^L||19510822|F OBR|1|ORD8842^EPIC|LAB77213^LABSYS|CBC^COMPLETE BLOOD COUNT^L|||20240314103000|||||||||1447312^OKONKWO^ADAEZE^^^^MD||||||20240314141000|||F OBX|1|NM|718-7^HEMOGLOBIN^LN||11.8|g/dL|12.0-15.5|L|||F|||20240314141000
Every field
| SEQ | LEN | DT | OPT | RP/# | TBL# | ITEM# | Element name | Cardinality |
|---|---|---|---|---|---|---|---|---|
| MSH-1 | 1 | ST | R | 00001 | Field Separator | 1..1 | ||
| MSH-2 | 4 | ST | R | 00002 | Encoding Characters | 1..1 | ||
| 227 | HD | O | 0361 | 00003 | Sending Application | 0..1 | ||
| ||||||||
| 227 | HD | O | 0362 | 00004 | Sending Facility | 0..1 | ||
| ||||||||
| 227 | HD | O | 0361 | 00005 | Receiving Application | 0..1 | ||
| ||||||||
| 227 | HD | O | 0362 | 00006 | Receiving Facility | 0..1 | ||
| ||||||||
| 26 | TS | R | 00007 | Date/Time Of Message | 1..1 | |||
| ||||||||
| MSH-8 | 40 | ST | O | 00008 | Security | 0..1 | ||
| 15 | MSG | R | 00009 | Message Type | 1..1 | |||
| ||||||||
| MSH-10 | 20 | ST | R | 00010 | Message Control ID | 1..1 | ||
| 3 | PT | R | 00011 | Processing ID | 1..1 | |||
| ||||||||
| 60 | VID | R | 00012 | Version ID | 1..1 | |||
| ||||||||
| MSH-13 | 15 | NM | O | 00013 | Sequence Number | 0..1 | ||
| MSH-14 | 180 | ST | O | 00014 | Continuation Pointer | 0..1 | ||
| MSH-15 | 2 | ID | O | 0155 | 00015 | Accept Acknowledgment Type | 0..1 | |
| MSH-16 | 2 | ID | O | 0155 | 00016 | Application Acknowledgment Type | 0..1 | |
| MSH-17 | 3 | ID | O | 0399 | 00017 | Country Code | 0..1 | |
| MSH-18 | 16 | ID | O | Y | 0211 | 00692 | Character Set | 0..* |
| 250 | CE | O | 00693 | Principal Language Of Message | 0..1 | |||
| ||||||||
| MSH-20 | 20 | ID | O | 0356 | 01317 | Alternate Character Set Handling Scheme | 0..1 | |
| 427 | EI | O | Y | 01598 | Message Profile Identifier | 0..* | ||
| ||||||||
Open this MSH message in HL7 Studio
Field notes
MSH-1Field Separator
The field separator, and the only field whose value is the delimiter itself. It is the fourth character of the message, and by universal convention it is a pipe. MSH-1 is counted as field 1 even though nothing precedes it, which is why every MSH field appears one position further right than the same count in any other segment. A parser that splits MSH on the separator and indexes from zero will be off by one for the whole segment.
Open MSH-1 in HL7 StudioMSH-2Encoding Characters
The encoding characters, in a fixed order: component, repetition, escape, subcomponent. Almost always `^~\&`. Read them, do not assume them. A sender that has chosen different characters is conformant, and a hardcoded parser will produce garbage where it should have produced an error, which is the worse of the two failures. MSH-2 also breaks the field-counting rule a second time: its four characters include the repetition separator, and it is nonetheless one field, not a repeating one.
Open MSH-2 in HL7 StudioMSH-4Sending Facility
Sending facility, which scopes the identifiers everywhere else in the message. The MRN in PID-3 means nothing without knowing which organisation issued it, and this field plus PID-3 component 4 are how a receiver works that out. Routing decisions in an interface engine usually hang off MSH-3 and MSH-4 together.
Open MSH-4 in HL7 StudioMSH-7Date/Time Of Message
Date and time of the message, which is when it was created and not when the clinical event happened. EVN-2 carries the event time for ADT, and OBR-7 carries the observation time for results. Using MSH-7 as the clinical timestamp puts every event at the moment the interface happened to fire.
Open MSH-7 in HL7 StudioMSH-9Message Type
Message type as three components: the type in component 1, the trigger event in component 2, and the message structure in component 3. `ADT^A01^ADT_A01` says an ADT message, triggered by an admit, laid out according to the ADT_A01 structure. Component 3 became required in v2.4, and older senders leave it empty. Where it is empty, the structure has to be inferred from the first two, and for ADT that inference is mostly safe because many events share one structure.
Open MSH-9 in HL7 StudioMSH-10Message Control ID
Message control ID, unique per sending application, and the value the receiver echoes in MSA-2 to acknowledge. Deduplication depends on it. A sender that reuses control IDs across a restart will have its retries silently accepted as new messages.
Open MSH-10 in HL7 StudioMSH-11Processing ID
Processing ID: P for production, D for debugging, T for training. A receiver in production should reject anything not marked P, and a surprising amount of test data reaches production systems because nothing checked this field.
Open MSH-11 in HL7 StudioMSH-12Version ID
Version ID. This tells the receiver how to parse everything after it, so it has to be read before anything else in the message is interpreted. It gives the version of the standard, and not the version of the interface: a sender running a v2.5.1 profile over a v2.3 feed still declares the version whose grammar the message follows.
Open MSH-12 in HL7 StudioMSH-15Accept Acknowledgment Type
Accept acknowledgment type, and MSH-16 application acknowledgment type. Together they say whether the sender wants a commit acknowledgment, an application acknowledgment, both, or neither, and under which conditions. AL means always, NE means never, ER means on error only, SU means on success only. Interfaces stall most often because one side expects an acknowledgment these two fields never requested.
Open MSH-15 in HL7 StudioMSH-18Character Set
Character set. When it is absent the standard says to assume ASCII, which is wrong for most real feeds carrying names. A message that declares nothing and contains a name with a diacritic is already relying on the receiver guessing correctly.
Open MSH-18 in HL7 Studio
Vendor behaviour
What follows describes patterns common to these systems' standard interfaces. Every installation is configured, so confirm against the interface specification for the site you are integrating with.
Epic
Epic interfaces are configured per connection, so MSH-3 and MSH-4 carry whatever was agreed during implementation and nothing Epic-wide, and they are the fields to confirm in writing before go-live. Epic populates MSH-9 component 3 with the structure code on modern builds.
Mapping to FHIR
MSH corresponds to FHIR MessageHeader, but only when the FHIR side is genuinely using the messaging paradigm. Most v2-to-FHIR work is not: it turns an ADT feed into Patient and Encounter resources through a REST API, and in that case MSH carries no clinical content to map and becomes provenance instead. Sending facility and message timestamp belong in a Provenance resource, and the message control ID is worth keeping as a Provenance identifier for tracing.
| HL7 v2 | FHIR R4 | Note |
|---|---|---|
| MSH-3, MSH-4 | MessageHeader.source | or Provenance.agent when not using messaging |
| MSH-5, MSH-6 | MessageHeader.destination | |
| MSH-7 | MessageHeader.meta.lastUpdated | or Provenance.recorded |
| MSH-9 | MessageHeader.eventCoding | |
| MSH-10 | Bundle.identifier |
Parsing pitfalls
MSH field numbering is off by one against every other segment
In PID, the text before the first pipe is the segment identifier and PID-1 follows it. In MSH, the first pipe is MSH-1. So MSH-9 is the eighth pipe-delimited value after the segment identifier, not the ninth. Every v2 parser has this special case, and every hand-rolled one has had this bug.
Assuming the delimiters instead of reading them
MSH-2 exists so that the message can declare its own encoding characters. Hardcoding
^~\&works until a sender uses something else, and the failure is silent: fields parse into the wrong shape and nothing throws.MSH-12 read after the fact
The version determines the grammar, so it has to be extracted before structural parsing begins, not looked up afterwards. Parsing a v2.3 message with v2.5.1 field definitions puts values in the wrong fields for every segment where the layout changed.
Trusting MSH-9 component 3 on older feeds
The message structure component was optional before v2.4 and is regularly empty. Code that keys its dispatch table on component 3 alone will drop every message from an older sender.
Related
- MSAthe acknowledgment that echoes MSH-10
- EVNcarries the event time that MSH-7 is often mistaken for
- ERRerror detail accompanying a negative acknowledgment
- PIDthe patient the message is about, scoped by MSH-4
Message types carrying MSH
MSH appears in 187 message structures, belonging to 106 message types.
- ADR
- ADT25
- BAR6
- BPS
- BRP
- BRT
- BTS
- CRM
- CSU
- DFT2
- DOC
- EAC
- EAN
- EAR
- ESR
- ESU
- INR
- INU
- LSU
- MDM2
- MFK
- MFN15
- MFQ
- MFR5
- NMD
- NMQ
- NMR
- OMB
- OMD
- OMG
- OMI
- OML3
- OMN
- OMP
- OMS
- ORB
- ORD
- ORF
- ORG
- ORI
- ORL3
- ORM
- ORN
- ORP
- ORR
- ORS
- ORU2
- OSQ
- OSR
- OUL4
- PEX
- PGL
- PMU5
- PPG
- PPP
- PPR
- PPT
- PPV
- PRR
- PTR
- QBP6
- QCN
- QRY4
- QSB
- QVR
- RAR
- RAS
- RCI
- RCL
- RDE
- RDR
- RDS
- RDY
- REF
- RER
- RGR
- RGV
- ROR
- RPA
- RPI2
- RPL
- RPR
- RQA
- RQC
- RQI
- RQP
- RRA
- RRD
- RRE
- RRG
- RRI
- RSP10
- RTB3
- SIU
- SQM
- SQR
- SRM
- SRR
- SSR
- SSU
- SUR
- TCU
- VXQ
- VXR
- VXU
- VXX