England Pathology and Laboratory Medicine (PaLM) Technical Framework
0.1.0 - ci-build
England Pathology and Laboratory Medicine (PaLM) Technical Framework - Local Development build (v0.1.0) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions
This page describes how to convert between the HL7 v2.5.1 messages and the FHIR R4 resources in this guide, in both directions. It follows the HL7 Version 2 to FHIR IG (message, segment, data type and vocabulary maps) and adds the England rules. The mappings are indicative: test them against your own interfaces.
There are four levels:
| HL7 v2.5.1 | FHIR container | MessageHeader.eventCoding | Focus | HL7 v2-to-FHIR |
|---|---|---|---|---|
OML^O21^OML_O21 |
Bundle Message, Laboratory Order (O21) | v2-0003 O21 |
ServiceRequest | OML_O21 to Bundle |
ORL^O22^ORL_O22 |
Bundle Message (response) | v2-0003 O21 |
- | - |
ORU^R01^ORU_R01 |
Bundle Message, Laboratory Result (R01) | v2-0003 R01 |
DiagnosticReport | ORU_R01 to Bundle |
ORU^R01^ORU_R01 (to NHS England) |
Bundle - Laboratory Report Document | - | Composition | see FHIR Message to FHIR Document |
ACK^R01^ACK |
Bundle Message (response) | v2-0003 R01 |
- | - |
The Bundle identifier is MSH-10 and timestamp is MSH-7. Each HL7 v2 message becomes
one FHIR Message; resources referenced from several segments (the Patient, the
requester's PractitionerRole) appear once in the Bundle.
Practitioners and organisations are identifier references in a FHIR Message. HL7 v2
carries only their codes and names - the ODS code (XON-10, MSH-4 / MSH-6, PL-10) and the GMC,
GMP or NMC code (XCN-1 with XCN-9). The FHIR Message mirrors that: a Reference with type,
identifier and display, and no Practitioner or Organization resource in the Bundle. When
a FHIR Document is built (below) they are looked up and
added, because the NHS England API needs them.
| Segment | FHIR resource | Profile | HL7 v2-to-FHIR |
|---|---|---|---|
| MSH | MessageHeader, Bundle | MessageHeader | MSH to MessageHeader |
| PID | Patient | Patient | PID to Patient |
| PV1 | Encounter, and the requester (PV1-3, PV1-8) | PractitionerRole, Organization | PV1 to Encounter |
| ORC | ServiceRequest | Laboratory Order | ORC to ServiceRequest |
| TQ1 | ServiceRequest.priority, occurrence | Laboratory Order | TQ1 to ServiceRequest |
| OBR (OML) | ServiceRequest | Laboratory Order | OBR to ServiceRequest |
| OBR (ORU) | DiagnosticReport (and the ServiceRequest it is basedOn) | Laboratory Report | OBR to DiagnosticReport |
| NTE | Annotation on the parent resource, or DiagnosticReport.conclusion |
NTE to ServiceRequest, NTE to Observation | |
| DG1 | ServiceRequest.reasonCode (or Condition) | DG1 to Condition | |
| OBX (results) | Observation | Laboratory Result | OBX to Observation |
OBX (ED, RP) |
DiagnosticReport.presentedForm (or DocumentReference + Binary) | Laboratory Report | OBX to DocumentReference |
| SPM | Specimen | Specimen | SPM to Specimen |
| MSA | MessageHeader.response | MessageHeader | MSA to MessageHeader |
Field by field mappings are on HL7 v2.5.1 Segments (FHIR column) and on each profile's Mappings tab.
DiagnosticReport.code is the report type (SNOMED CT 721981007
Diagnostic studies report, LOINC 11502-2), not OBR-4code and the OBX as hasMember - NHS England calls this an organizer (for
example the FBC, LFT, U&E). When an OBR has a single OBX (a single test, such as HbA1c),
that result Observation is used directly. Either way it is one DiagnosticReport.resultcode, and the requester;
DiagnosticReport.basedOn and each Observation's basedOn reference itvalue^namespace
(for example REQ-20220307-000046-001^B82033); the FHIR Identifier.system (a URI) is
not known at that stage of the pipeline and SHOULD NOT be expected in the HL7 v2
message. The converter - usually the integration engine - assigns it from an agreed table
of field (placer order, report, placer specimen, accession) and namespace to system,
and keeps the namespace as the assigner (ODS code)PLAC
identifier or ORC-2 into a FILL identifierC) SHALL
update the same DiagnosticReport and Observations. Use stable identifiers - the
DiagnosticReport by OBR-3, each Observation by OBR-3 + OBX-3 (+ OBX-4) - and make the
FHIR id deterministic from them, not from OBX-1, which can change between versions of
a reportDiagnosticReport.conclusion
(several NTE are joined with new lines); NTE after an OBX become Observation.noteFT with \.br\ line
breaks, or several TX OBX with the same OBX-3, one per line as in many microbiology
reports - becomes one Observation with the lines joined in valueString, as in the
NHS England unstructured examples (GTT, urine MCS), not one Observation per line| OBX-2 | Meaning | FHIR Observation.value[x] |
Notes |
|---|---|---|---|
NM |
Numeric | valueQuantity |
value = OBX-5, units from OBX-6 (UCUM system http://unitsofmeasure.org) |
SN |
Structured numeric | valueQuantity with comparator (<^10), or valueRange (^10^-^20), or valueRatio (^1^:^128) |
< <= > >= go in Quantity.comparator |
CWE / CE |
Coded | valueCodeableConcept |
For example organism or Positive / Negative (SNOMED CT) |
ST |
String | valueString |
|
TX / FT |
Text / formatted text | valueString (or DiagnosticReport.presentedForm - see Rules) |
\.br\ becomes a new line |
DT |
Date | valueDateTime |
|
TS / DTM |
Date and time | valueDateTime |
|
TM |
Time | valueTime |
|
ED |
Encapsulated data | not an Observation - see Embedded Documents | |
RP |
Reference pointer | not an Observation - see Embedded Documents |
An empty OBX-5 with OBX-11 = X (cannot be obtained) or N (not asked) becomes an
Observation with no value and dataAbsentReason (error / not-asked).
OBX-7 is a string. Parse the common forms; otherwise keep the text.
| OBX-7 | Observation.referenceRange |
|---|---|
115-165 |
low 115, high 165 (units from OBX-6) |
<48 |
high 48 (Open - < vs <=; EU Laboratory has highComparator modifier extensions) |
>4.0 |
low 4.0 (as above) |
| anything else | text |
| OBX field | FHIR |
|---|---|
OBX-2 ED |
DiagnosticReport.presentedForm (Attachment) |
OBX-5 ED-2 / ED-3 (for example application / pdf) |
presentedForm.contentType = application/pdf |
| OBX-5 ED-5 (Base64) | presentedForm.data, or a Binary referenced by presentedForm.url (NW GMSA convention - prefer the url) |
OBX-2 RP, OBX-5 URL |
presentedForm.url |
| OBX-3 | presentedForm.title (display text) |
Join split ED OBX (same OBX-3, consecutive) before decoding.
| HL7 v2 | FHIR | Notes |
|---|---|---|
| CX | Identifier | CX. CX-4 NHS → system https://fhir.nhs.uk/Id/nhs-number; CX-5 → type (v2-0203) |
| EI | Identifier | EI. EI-1 → value; EI-2 namespace → assigner and, through an agreed table, system (not sent in HL7 v2) |
| XCN | Reference(Practitioner) / PractitionerRole | XCN. XCN-9 → identifier.system |
| XON | Reference(Organization) | XON. XON-10 → ODS identifier |
| XPN | HumanName | |
| XAD | Address | XAD-5 → postalCode |
| XTN | ContactPoint | XTN-2 → use, XTN-3 → system |
| CWE / CE / CNE | CodeableConcept / Coding | CWE-1/2/3 and CWE-4/5/6 → two coding; CWE-3 → system - see Terminology; CWE-9 → text |
| TS / DTM | dateTime / instant | YYYYMMDDHHMMSS[+ZZZZ] → YYYY-MM-DDThh:mm:ss+zz:zz. With no time zone, assume UK local time (Europe/London) |
| DR | Period | SPM-17 |
| NM + CWE (OBX-5 + OBX-6) | Quantity | |
| SN | Quantity / Range / Ratio | see OBX-2 |
| ED | Attachment |
The HL7 v2 tables that change meaning between HL7 v2 and FHIR are mapped by ConceptMaps in this guide:
| HL7 v2 table | Field | FHIR element | ConceptMap |
|---|---|---|---|
| 0001 Administrative Sex | PID-8 | Patient.gender |
v2-0001-to-administrative-gender |
| 0119 Order Control | ORC-1 | ServiceRequest.status |
v2-0119-to-request-status |
| 0485 Extended Priority | TQ1-9 | ServiceRequest.priority |
v2-0485-to-request-priority |
| 0123 Result Status | OBR-25 | DiagnosticReport.status |
v2-0123-to-diagnostic-report-status |
| 0085 Observation Result Status | OBX-11 | Observation.status |
v2-0085-to-observation-status |
| 0078 Interpretation Codes | OBX-8 | Observation.interpretation |
v2-0078-to-observation-interpretation |
Tables used as-is (the FHIR code system is the HL7 v2 table): 0203 Identifier Type
(Identifier.type), 0074 Diagnostic Service Section ID (DiagnosticReport.category),
0003 Event Type (MessageHeader.eventCoding).
The same tables read right to left. Points to watch:
equivalence equivalent first; registered → OBR-25 I (not O), partial → A,
preliminary → P, amended → C, entered-in-error → OBX-11 WbasedOn), all with OBR-3 = DiagnosticReport.identifier. A test group Observation
(with hasMember) becomes the OBR (its code → OBR-4) and its members the OBX; a single
result is an OBR with one OBX. OBX-1 is numbered from 1 for each OBRIdentifier.system in EI-3 / EI-4 - send value^namespace, the receiver
assigns the systemServiceRequest.identifier (PLAC) → ORC-2 / OBR-2, (FILL) → ORC-3 /
OBR-3; Patient.identifier → PID-3 repeats; an NHS Number SHALL be sent as
<number>^^^NHS^NHcoding (SNOMED CT) → CWE-1/2/3, second (LOINC) → CWE-4/5/6SN, otherwise NM; valueString → ST
(or TX / FT for multi-line text); valueCodeableConcept → CWEED, split into chunks if the receiver
requires itsender / destination.receiver ODS codes → MSH-4 / MSH-6,
source.name / destination.name → MSH-3 / MSH-5, Bundle.identifier → MSH-10The NHS England Pathology Laboratory Reporting API needs a FHIR Document. From a Laboratory Result (R01) message (or directly from an ORU_R01), for each DiagnosticReport:
epraccur.csv GP practices, etr.csv trusts); GP practitioners (GMP codes) from the ODS
download egpcur.csv; other clinicians from the system's own practitioner directorysubject = the Patient, with subject.identifier = the NHS Number; identifier =
the DiagnosticReport's Filler Order Number (OBR-3); type = the report type
(721981007 and 11502-2, the same as DiagnosticReport.code - HL7 Europe requires the
Composition and DiagnosticReport to share an identifier and a code); date =
DiagnosticReport.issued; author, attester and custodian = the performing
laboratory; one section per test group (OBR) with generated narrative and an entry
for its Observation - see
Human Readable and Computer ProcessableDiagnosticReport.composition
extension (HL7 Europe DiagnosticReport-eu-lab), and mark each test group Observation with the
NHS England Observation.organizer extensiontype document with a new
identifier and timestampmeta.profile on every resource and drop the MessageHeaderWorked through for the NHS England examples in notebook
02-fhir-message-to-fhir-document;
the HL7 v2 to FHIR Message step is notebook
01-oru-r01-to-fhir-message,
and the reverse (FHIR Document to ORU^R01) is
scripts/nhse_document_to_oru.py
The LAB-3 example ORU^R01 and its FHIR equivalents:
| HL7 v2 | FHIR Message | FHIR Document |
|---|---|---|
| MSH | MessageHeader (inline) | - |
| PID | Patient | the same Patient |
| PV1-3, PV1-8, ORC-12, ORC-21 | PractitionerRole, Practitioner, Organization | the same |
| ORC | Laboratory Order | the same |
| OBR-3, OBR-22, OBR-25, NTE | Laboratory Report | the same report, plus the Composition link |
| OBR (test group, OBR-4) | FBC test group | the same |
| OBR-32 | PractitionerRole | the same |
| OBX-1 to OBX-7 | White cell count, Haemoglobin, Platelets, Red cell count, Haematocrit, MCV, MCH | the same |
| OBX-23 | Organization - MFT | the same |
| SPM | Specimen | the same |
| - | - | Composition, Provenance |
Bundles: FHIR Message and FHIR Document.
For one result, OBX-2:
OBX|2|NM|1022431000000105^Haemoglobin estimation^SCT^718-7^Hemoglobin [Mass/volume] in Blood^LN||112|g/L^^UCUM|115-165|L|||F|||20261103091500|||||||||Manchester University NHS Foundation Trust^^^^^^^^^R0A
| Field | Value | FHIR (Observation) |
|---|---|---|
| OBX-2 | NM |
valueQuantity |
| OBX-3 | 1022431000000105^Haemoglobin estimation^SCT^718-7^...^LN |
code.coding[0] = SNOMED CT 1022431000000105, code.coding[1] = LOINC 718-7 |
| OBX-5, OBX-6 | 112, g/L^^UCUM |
valueQuantity = 112 g/L (UCUM) |
| OBX-7 | 115-165 |
referenceRange.low 115 g/L, high 165 g/L |
| OBX-8 | L |
interpretation = v3-ObservationInterpretation L |
| OBX-11 | F |
status = final |
| OBX-14 | 20261103091500 |
effectiveDateTime = 2026-11-03T09:15:00Z |
| OBX-23 | ...^R0A |
performer = Organization R0A |
| OBR-22 | 20261103160500 |
issued |
| OBR-2, SPM | basedOn, specimen |