Short answer: a laboratory interface has two directions. Orders go from the EHR to the laboratory information system (LIS) as HL7 v2 ORM^O01 or OML^O21 messages (or as FHIR ServiceRequest), and the LIS answers with ORR/ORL and later with results as ORU^R01 (or FHIR DiagnosticReport with Observations). The hard parts are not the messages but the details inside them: placer and filler numbers that tie results to orders, result status (preliminary, final, corrected), abnormal flags, units and reference ranges, specimen information, microbiology with its multi-part results, and code mapping to LOINC. Done well, every result lands on the right patient, the right order and the right place in the chart, with its meaning intact.
Step 1: agree the flows
The first step in integrating a laboratory information system with an EHR is agreeing with the laboratory which flows exist: orders out, order status updates, results in, corrections, cancellations, add-on and reflex tests, and an ADT demographics feed to the LIS. The parties also fix the HL7 version, usually 2.3.1 or 2.5.1, and the transport, typically MLLP with acknowledgements.
Decide with the laboratory which flows exist: orders out (or does the lab receive paper and register itself?), order status updates, results in, corrections, cancellations, add-on tests, reflex tests, and demographics (ADT feed to the LIS so it knows the patient before the specimen arrives). Draw the sequence for a normal result, a corrected result and a cancelled order. Decide the HL7 version (2.3.1 and 2.5.1 are most common) and the transport (MLLP with ACKs; sometimes files). See HL7 v2 order messages.
Step 2: the result message, field by field
A laboratory result arrives at the EHR as an HL7 v2 ORU^R01 message: MSH identifies sender and receiver, PID the patient, PV1 the visit, ORC and OBR carry the placer and filler order numbers, the ordered panel and the report status, and each OBX holds one analyte with its LOINC code, value, units, reference range, abnormal flag and result status.
MSH|^~\&|LIS|CENTRALLAB|EHR|GENHOSP|20260314130500||ORU^R01^ORU_R01|RES0001|P|2.5.1
PID|1||MRN-00012345^^^GENHOSP^MR||DOE^JANE||19800523|F
PV1|1|O|CLINIC-3^^^GENHOSP
ORC|RE|PLC-778812^EHR|FIL-556701^LIS|||||||||42^SMITH^JOHN
OBR|1|PLC-778812^EHR|FIL-556701^LIS|58410-2^CBC panel - Blood by Automated count^LN|||20260314084000|||||||||42^SMITH^JOHN||||||20260314130000|||F
OBX|1|NM|718-7^Hemoglobin [Mass/volume] in Blood^LN||10.9|g/dL|12.0-15.5|L|||F|||20260314125800
OBX|2|NM|6690-2^Leukocytes [#/volume] in Blood by Automated count^LN||6.4|10*3/uL|4.0-10.0|N|||F|||20260314125800
OBX|3|NM|777-3^Platelets [#/volume] in Blood by Automated count^LN||230|10*3/uL|150-400|N|||F|||20260314125800
NTE|1||Mild normocytic anaemia; suggest iron studies if clinically indicated.
- ORC-2 / OBR-2 placer number and ORC-3 / OBR-3 filler number: the join to the order. OBR-4: the panel, coded (LOINC
LN). OBR-7: specimen collection time. OBR-22: results report time. OBR-25: result status for the whole order (Ppreliminary,Ffinal,Ccorrected,Xcancelled). - OBX-2: value type (
NMnumeric,STstring,TXtext,CE/CWEcoded,SNstructured numeric such as<^5). OBX-3: the analyte, coded. OBX-5: the value. OBX-6: units, ideally UCUM (10*3/uL, notK/µL). OBX-7: reference range as text. OBX-8: abnormal flags (L,H,LL,HH,A,N). OBX-11: result status per analyte (P,F,C,X,Ddeleted). OBX-14: observation time. OBX-19: analysis time. - NTE: comments, attached to the OBR or to a specific OBX by position.
- SPM (2.5+): specimen type (SNOMED CT), collection time, received time, condition.
Step 3: the special cases
The special cases a laboratory interface must handle are corrected results (status C with the original order numbers, replacing and alerting rather than deleting), preliminary then final results, microbiology with organisms and susceptibilities linked by sub-ID, text results and embedded PDFs, reflex and add-on tests, cancellations, and units and reference ranges that change when the laboratory changes analysers.
- Corrections: a new ORU with
Cin OBR-25 and OBX-11 and the same placer/filler numbers; the EHR must replace, flag the change and alert the clinician. Never delete the original silently. - Preliminary then final:
Presults (a Gram stain) followed byF(the culture); the chart must show the status. - Microbiology: one OBX for the organism identified (coded, SNOMED CT), then susceptibility results as OBX per antibiotic with the organism as a sub-ID (OBX-4), often across several messages. This is where most interface bugs hide.
- Text results and PDFs: pathology and some chemistry comments arrive as TX lines or as an embedded PDF (OBX-2
ED); the chart needs both the text and the file. - Reflex and add-on tests: new OBRs under the original order, or a new order created by the lab; agree how they are numbered.
- Cancellations:
Xstatus, with the original numbers. - Units and ranges per analyser: the same test can change units when the laboratory changes analysers; the interface must carry the range with each result, not assume it.
Step 4: codes
Code mapping in a laboratory interface means translating the laboratory's local test codes to LOINC once, in a maintained table, and sending both the local and the LOINC code in OBX-3, normalising units to UCUM, and coding specimen types and organisms in SNOMED CT. Without this mapping, results cannot be trended across laboratories or read by external systems.
Map the laboratory's test codes to LOINC once, in a maintained table, and send both local and LOINC codes in OBX-3 (GLU^Glucose^L~2345-7^Glucose [Mass/volume] in Serum or Plasma^LN). Normalise units to UCUM. Specimen types and organisms in SNOMED CT. The method is in How to map local lab codes to LOINC; without it, results cannot be trended across laboratories or read by any external system.
Step 5: the FHIR alternative
The FHIR alternative to an HL7 v2 laboratory interface uses a ServiceRequest for the order, one Observation per analyte with a LOINC code, UCUM quantity, reference range and interpretation, and a DiagnosticReport that groups them with status, performer, issued time, conclusion and PDF. Delivery is REST writes, a transaction Bundle per report, or FHIR Subscriptions.
With FHIR, the order is a ServiceRequest, the results are Observations (one per analyte, LOINC code, UCUM quantity, referenceRange, interpretation) grouped by a DiagnosticReport that carries status, performer, issued time, the conclusion and the PDF, with basedOn pointing to the ServiceRequest. Corrections are versions of the same resources with status amended or corrected. Delivery is REST writes to the EHR's FHIR server, a transaction Bundle per report, or Subscriptions. The HL7 v2-to-FHIR guide maps every field above; many laboratories now offer both. See FHIR DiagnosticReport explained and FHIR Observation explained.
Step 6: testing and go-live
Testing a laboratory interface before go-live means running synthetic patients through every special case, comparing a day of parallel results between the laboratory's report and the EHR chart, checking time zones and daylight-saving transitions, verifying acknowledgement handling and replay after an outage, and agreeing an on-call procedure for failed messages, using IHE's Laboratory Testing Workflow profile as a baseline.
Test with synthetic patients through every case in step 3; compare a day of parallel results between the paper or PDF report and the chart; check time zones and daylight-saving transitions; verify ACK handling and replay after an outage; agree an on-call procedure for failed messages. IHE's Laboratory Testing Workflow profile and national conformance suites give a tested baseline.
Failures to design against
The failures a laboratory interface must be designed against are results filed to a previous encounter, patient merges not applied to the LIS, unit changes after an analyser upgrade shifting trends, corrected results overwriting without an alert, microbiology susceptibilities attached to the wrong organism, and results for tests the EHR has no code for vanishing into an error queue.
Results filed to a previous encounter because PV1 was stale; a merge (ADT A40) not applied to the LIS; a unit change after an analyser upgrade silently shifting trends; corrected results overwriting without an alert; microbiology susceptibilities attached to the wrong organism; a lab sending results for a test the EHR has no code for, which then vanish into an error queue.
In Anpheros
The Anpheros lab connector accepts ORU^R01, CSV and JSON and produces Observations under a DiagnosticReport with LOINC and UCUM, keeping local codes and the original file; the developer guide on importing lab results walks through it against the free sandbox.
Related pages
- HL7 v2 ORM and OML order messages
- HL7 v2 messages explained: ADT and ORU
- How to map local lab codes to LOINC
- FHIR DiagnosticReport explained
- Lab connector: HL7 v2, CSV or JSON to FHIR
- Interface engines explained
- Import lab results into FHIR (developer site)
Sources
- HL7 v2.5.1 ORU_R01 reference (Caristix)
- HL7 v2.5.1 OBX segment (Caristix)
- IHE Laboratory technical framework (LTW)
- HL7 v2-to-FHIR implementation guide
- HL7 FHIR R4: DiagnosticReport
Frequently asked questions
Which HL7 version should a new lab interface use?
2.5.1 if both sides support it: it has SPM for specimens and clearer status handling. Many laboratories still run 2.3.1, and the interface adapts to the older side.
How are results matched to orders?
By the placer order number (assigned by the EHR) and the filler order number (assigned by the LIS), carried in ORC-2/3 and OBR-2/3 of both the order response and the result. If the EHR never recorded the filler number, matching falls back to the placer number.
What if the laboratory cannot send LOINC codes?
Map their local codes to LOINC on your side, in the engine or the connector, and keep both. Insist that the local code system is stable and that new tests are announced.
Is FHIR ready for lab interfaces?
Yes for new connections, especially outside the hospital: ServiceRequest, Observation and DiagnosticReport cover orders and results fully, and national guides profile them. Inside the hospital, the LIS and analysers will speak HL7 v2 for years.
Try it free in the sandbox
Your first FHIR call in 5 minutes. An HL7 FHIR R4 API with the patient's consent built in: try it in the sandbox, then connect your own app or clinic system.
Free · 30 synthetic patients · no card

The more you log, the clearer your record
Your health history in one place, under your control.
Free · Works in your browser · No card
