HL7 ORU and ORM Messages: What Lab Software Must Handle

L
LIS Bridge
Aug 30, 2026
HL7 ORU and ORM Messages: What Lab Software Must Handle

An HL7 lab integration guide to ORU and ORM messages — segment by segment, what each field means, and the handling every LIS interface has to get right.

HL7 ORU and ORM Messages: What Lab Software Must Handle

Almost every conversation about hospital interoperability eventually lands on HL7, and almost every one of them stays at the level of "we speak HL7." That statement is close to meaningless. HL7 v2 defines dozens of message types across admissions, scheduling, billing, pharmacy, and orders. A laboratory interface only ever needs a small number of them, and two carry nearly all the traffic: ORM, which requests that a test be performed, and ORU, which reports what the test found.

If you are specifying a lab interface, evaluating middleware, or debugging a feed that keeps rejecting messages, those two structures are the thing to understand in detail. This HL7 lab integration guide walks through both — segment by segment, field by field where it matters — and then covers the handling that separates an interface that works in a demo from one that works at 2 a.m. on a Sunday.

One clarification before starting, because it causes real confusion: HL7 is not the protocol your analyzer speaks. The bench instrument almost certainly emits ASTM E1394 over a serial cable or a TCP socket. HL7 lives one hop upstream, between the middleware and the hospital information system. If that distinction is new, read HL7 vs. ASTM E1394 first — the rest of this post assumes it.

The Two Messages and the Direction They Travel

In a fully integrated lab, data moves in a loop:

  1. A clinician orders a test in the HIS or EHR.
  2. The HIS emits an ORM^O01 (order message) toward the lab system.
  3. The lab system — or the middleware in front of it — turns that order into something the analyzer understands and dispatches it.
  4. The analyzer runs the sample and emits results in its native protocol.
  5. The middleware parses those results and emits an ORU^R01 (observation result message) back to the HIS.
  6. The result appears in the patient's chart.

ORM travels downstream, toward the bench. ORU travels upstream, toward the chart. A results-only interface implements step 5 and skips steps 2 through 4 — which is where a great deal of lab middleware stops, and why "bidirectional" is a term worth checking carefully when a vendor uses it.

A note on versions, since it comes up in every procurement conversation. ORM^O01 is the classic order message from HL7 v2.3 and v2.3.1. From v2.4 onward, HL7 formally deprecated it in favour of the domain-specific OML^O21 laboratory order message. In practice the installed base is overwhelmingly v2.3.1, and a lab interface built in 2026 still has to handle ORM. Support both; assume neither.

ORU^R01: The Result Message, Segment by Segment

An ORU message is a nested structure. At the top is the message header, then patient identity, then one or more orders, and under each order one or more observations. The hierarchy is the point — it is what lets a single message carry a full CBC panel rather than twenty separate messages.

MSH — Message Header

Every HL7 message starts with MSH. It carries the encoding characters, the sending and receiving application and facility, a timestamp, the message type, and a control ID.

Three fields cause most of the trouble. MSH-9 (message type) must read ORU^R01 — some systems are strict about the trigger event component and reject a bare ORU. MSH-10 (message control ID) must be unique, because it is what an acknowledgement refers back to; reusing control IDs makes duplicate detection impossible on the receiving side. MSH-12 declares the version, and a receiver configured for 2.3.1 will often refuse a message that claims 2.5.1 even when the content is identical.

PID — Patient Identification

Patient identity, and the segment most likely to cause a message to be filed against the wrong chart or rejected outright. The critical field is PID-3, the patient identifier list. It is a repeating, component-structured field: identifier, assigning authority, identifier type code. A hospital that issues both an MRN and a national ID expects both, correctly qualified. Send a bare number with no assigning authority and the receiving system has to guess which namespace it belongs to.

PID-5 (patient name) is similarly component-structured — family name, given name, middle, suffix, prefix. Concatenating a full name into the first component is a common shortcut that survives testing and fails in production the moment someone searches by surname.

PV1 — Patient Visit

Optional in some configurations, mandatory in most hospital ones. It carries the encounter: patient class (inpatient, outpatient, emergency), assigned location, attending physician. Its practical importance is routing — many HIS installations use PV1 to decide which ward view or which clinician's inbox a result surfaces in.

OBR — Observation Request

OBR describes the order that produced the results. One OBR, one panel. OBR-2 is the placer order number, assigned by whoever requested the test; OBR-3 is the filler order number, assigned by the lab. Getting these right is what allows the HIS to match an incoming result to the order it issued rather than creating an orphan record.

OBR-4 is the universal service identifier — the test or panel code, ideally with a coding system such as LOINC. OBR-7 is the observation date/time, which for a lab result means specimen collection time, not analysis time. Clinicians read that field as "when was this blood drawn," and populating it with the timestamp the analyzer finished is a subtle but genuinely clinical error.

OBR-25 carries the result status: P preliminary, F final, C correction, X cannot be obtained. A correction that arrives without C tends to sit in the chart alongside the original value rather than replacing it.

OBX — Observation Result

This is the payload. One OBX per analyte. A CBC produces twenty or more of them under a single OBR.

  • OBX-2 — value type: NM numeric, ST string, TX text, CE coded entry. A numeric result sent as ST will display but will not trend or graph.
  • OBX-3 — observation identifier: the analyte code. Local analyzer codes here rather than LOINC is the single most common reason a result lands as unrecognised.
  • OBX-5 — the observation value itself.
  • OBX-6 — units.
  • OBX-7 — reference range.
  • OBX-8 — abnormal flags: H, L, HH, LL, A. These drive alerting on the clinical side, and dropping them means a critical potassium arrives looking like any other number.
  • OBX-11 — observation result status, per-analyte, mirroring the semantics of OBR-25.
  • OBX-14 — date/time of the observation.

NTE — Notes and Comments

NTE segments attach free text to the segment above them. Analyzers use them heavily — haemolysis flags, dilution notes, instrument comments. They are easy to ignore when building an interface and are frequently the only place an instrument records why a result should be treated with caution.

ORM^O01: The Order Message

ORM is smaller, and the segment that matters most is one that does not appear in ORU at all.

After MSH, PID and PV1, an ORM carries an ORC (common order) segment followed by an OBR. ORC-1 is the order control code, and it is the field that determines what the message actually means:

  • NW — new order
  • CA — cancel
  • OC — order cancelled (a response)
  • XO — change order
  • SC — status changed

An interface that treats every inbound ORM as a new order — a genuinely common shortcut — will happily create a duplicate specimen when the HIS sends a cancellation. ORC-1 is not optional handling.

ORC also carries the placer order number (ORC-2), the filler order number (ORC-3), the ordering provider (ORC-12), and the order date/time (ORC-9). Where ORC and OBR overlap, the values must agree; HL7 permits population in either, and receivers vary in which they read.

For laboratory orders there is one further segment worth knowing: SPM, the specimen segment, introduced properly in v2.5. It describes the specimen itself — type, collection method, container, collection time — separately from the test being requested. Where it is available it is a much cleaner place to put specimen detail than the OBR fields that were historically overloaded with it.

Acknowledgements: The Part That Gets Skipped

HL7 v2 messages are not fire-and-forget. Every message expects an ACK in return, carrying an MSA segment whose MSA-1 field holds an acknowledgement code:

  • AA — application accept
  • AE — application error
  • AR — application reject

MSA-2 echoes the original MSH-10 control ID, which is how sender and receiver correlate the exchange. There is also an enhanced acknowledgement mode that separates commit acknowledgement (CA/CE/CR — I have received and stored this) from application acknowledgement (I have processed it). Original mode conflates the two, and most installations run original mode.

Why this matters operationally: a sender that does not read ACKs cannot know a result was rejected. It will report success, the message will be gone, and the missing result will be discovered by a clinician looking for a value that never arrived. An interface that logs AE responses and retries or queues them is doing something meaningfully different from one that writes to a socket and moves on.

MLLP: How the Bytes Actually Move

HL7 v2 defines message content, not transport. In practice the transport is MLLP — Minimal Lower Layer Protocol — which wraps each message in a start block (0x0B), ends it with 0x1C 0x0D, and streams it over a plain TCP socket.

MLLP is minimal in the literal sense. It provides framing and nothing else: no encryption, no authentication, no built-in retry. Everything else — TLS, message queuing, reconnection — is the responsibility of the software at either end. A dropped TCP connection mid-stream can leave a partial message in the receiver's buffer, and an implementation that does not enforce block boundaries strictly will occasionally hand a truncated message to its parser.

This is also where dialect variation shows up in the field. Not every analyzer that speaks HL7 speaks it identically. In the LISBridge catalogue, the CXL PRO auto-chemistry analyzer emits HL7 v2.3.1 over MLLP and supports classic ASTM, with bidirectional operation in both dialects — a query in one is a QRY^Q02 answered by a DSR^Q03, and in the other a Q-record answered by an H/P/O/L worklist. Same instrument, two entirely different message grammars. An interface is only as broad as the dialects it actually implements.

What a Lab Interface Has to Get Right

Reading the specification is the easy half. The list below is what separates interfaces that hold up:

  • Handle both ORM^O01 and OML^O21. Assume the HIS you connect to next will use whichever one you did not build for.
  • Read ORC-1 before acting. A cancel is not a new order.
  • Read and act on ACKs. An unacknowledged message is an unknown outcome, not a successful one.
  • Preserve abnormal flags and result status. These are the fields with clinical consequence, and they are the first to be dropped in a simplified mapping.
  • Map codes deliberately. The analyzer's internal analyte code and the LIS's expected code will not match. Somebody has to define that mapping — the only question is whether it is you, in a configuration screen, or a vendor, on a support ticket.
  • Keep the raw message. When a clinician disputes a value six months later, the parsed record is an interpretation. The original bytes are evidence.
  • Survive the connection dropping. Reconnect with backoff, queue what could not be sent, and do not lose messages held in memory when the process restarts.

That last group is the reason to be sceptical of "we support HL7" as a capability statement. Supporting the message format is table stakes. Supporting the failure modes is the product.

A Note on FHIR

HL7 International continues to expand its FHIR accelerator programme — a Quality Improvement accelerator opened for founding members in August 2026, following Caliper for device interoperability and Helios before it. It is worth watching, and it is worth being honest about what it changes for a laboratory in the near term: not much at the bench.

FHIR is a modern REST and resource-oriented standard, and it is genuinely displacing v2 for application-to-application exchange at the top of the stack. The hematology analyzer downstairs still emits ASTM E1394 over a serial cable, and no accelerator is going to retrofit it. Interoperability initiatives keep starting at the EHR; interoperability actually starts at the instrument. LISBridge parses ASTM and HL7 v2 — that is the layer where lab data is either captured correctly or lost, and we would rather state that plainly than claim a standard we do not implement.

Frequently Asked Questions

What is the difference between ORU and ORM in HL7?

ORM^O01 is an order message: it requests that a test be performed and travels from the ordering system toward the lab. ORU^R01 is an observation result message: it reports findings and travels from the lab back toward the patient record. A complete lab interface handles both; a results-only interface handles ORU alone.

Is ORM^O01 deprecated?

Formally yes — HL7 deprecated ORM in favour of OML^O21 from v2.4 onward. Practically, no: the installed base of v2.3.1 systems still emitting ORM is very large, and any lab interface deployed today needs to handle it. Support both message types rather than choosing.

What does an OBX segment contain?

One observation — a single analyte result. It carries the value type, the observation identifier (ideally a LOINC code), the value itself, units, reference range, abnormal flags, result status, and observation time. A CBC panel produces twenty or more OBX segments grouped under a single OBR.

Does my analyzer send HL7 directly?

Usually not. Most bench analyzers emit ASTM E1394, a vendor-specific variant, or a proprietary format over serial or TCP. Some newer instruments do emit HL7 v2 over MLLP, and a few support both. Middleware exists to sit between the two and translate — which is why the analyzer's native protocol matters as much as the HIS's expected one.

What happens if the HIS rejects a result message?

It returns an ACK with MSA-1 set to AE or AR, referencing the original control ID. If the sending software reads acknowledgements, it can log, alert, and requeue. If it does not, the rejection is silent and the missing result surfaces later as a clinical question rather than a technical one.

Where LISBridge Sits

LISBridge is a native desktop application — Rust and Tauri, running locally on a machine in the lab — that connects to analyzers over RS-232 serial, TCP/IP, or FTP/FTPS/SFTP, parses what they emit, and delivers structured results onward to a HIS or LIMS. It supports 35 named instruments out of the box, 16 of them bidirectionally, meaning it dispatches orders to the analyzer as well as collecting results from it.

Practically, for the topics in this post: it parses ASTM E1394 and HL7 v2 natively, keeps the raw protocol data alongside every parsed result for traceability, and lets you map any analyzer parameter to any LIS field yourself — in the product, without a vendor ticket. Connections reconnect automatically with exponential backoff, and results are written to crash-safe local storage so a power cut does not take the queue with it.

If you want to see how the pieces fit together end to end, how LISBridge parses instrument data covers the parsing layer in more detail.

Start your free trial — no credit card required. lisbridge.com/pricing

Comments (0)

Leave a comment

No comments yet. Be the first to leave one!