Skip to content
DEXPRADEXPRA home
Tools

Interoperability

Available

FHIR Front for HL7 v2 Systems

A FHIR R4 API for systems that only send HL7 v2. It reads the feeds they already produce, keeps the current state of what they say as FHIR resources, and answers FHIR requests from it, so the source system does not change.

What it does

Two phases. Phase 1 is available on request as a beta. Phase 2 follows.

Phase 1 · Beta, on request

A read-only FHIR API from admission, results and scheduling feeds

The first release.

  • Receives ADT, ORU and SIU over MLLP, and acknowledges each message once it is stored.
  • Maps them to Patient, Encounter, ServiceRequest, Observation, DiagnosticReport and Appointment, from HL7’s v2-to-FHIR guide plus maps of its own for discharge and merge.
  • Keeps current state: updates, cancellations, corrections and late messages change the resource they belong to.
  • Serves a read-only FHIR R4 API with the searches US Core 6.1.0 requires.
  • Validates against US Core 6.1.0, with a system URL for each assigning authority. Appointment, which US Core does not profile, is base FHIR.
  • Links merged patient records (A40) instead of deleting either.
  • Points every resource back to its source message with a Provenance.
  • Authorizes every request, with SMART Backend Services.
  • Loads history by replaying archived messages.
  • A mapping workbench: paste a message, see the FHIR and the rule behind each element.

Phase 2 · Next

Apps for people, notifications, your codes, documents

Roughly in order. Tell us in your request which matters to you.

  • SMART App Launch, for apps used by a signed-in person.
  • Notifications when a resource changes, with HL7’s Subscriptions R5 Backport.
  • Your own code maps applied on the way in, original code kept.
  • Document notifications (MDM) as DocumentReference.
  • CA Core+ profiles, once Infoway publishes them as final.

Article · Interoperability

Putting a FHIR API in front of HL7 v2 systems

Many systems that hold the data a FHIR app wants only send HL7 v2. Putting an API in front of them is mostly about state, identity and what the feed never sent.

DEXPRA · 11 min read

Why a FHIR API is wanted from systems that only send v2

An app, an analytics pipeline or a partner asks for FHIR. The data is in a laboratory, radiology or scheduling system whose only way of saying anything is HL7 v2: a message when a patient arrives, when a result is final, when a slot is booked.

In the United States the electronic health record usually has a FHIR API already, because certification requires one and CMS’s Promoting Interoperability programs require certified health IT. Certification is voluntary and covers the products submitted to it. A system outside it has no API by that route.

v2 is not making way: in ONC’s 2023 survey, 96% of health information exchanges received v2 admission messages. Nothing published measures what share of a hospital’s own interfaces are v2, so this article does not guess. HL7 is four standards explains why v2 persists; this starts where that ends.

Three ways to put FHIR in front of v2

Ask the source, build from the feed, or convert on the way through. The choice decides what the API can answer.

Three shapes of a FHIR front

Structure

The choice decides what the API can answer. Pick a shape to see its request path.

Request path

Identity queries
  1. FHIR client
  2. FHIR search
  3. Front
  4. v2 query (QBP)
  5. Source system
  6. v2 reply (RSP)
What it can answer
Whatever the source holds, as of now.
Where it breaks
Only works if the source answers v2 queries. Nothing published measures how many systems do.
Seen in
IHE’s identity profiles: PIXm in front of a PIX manager, PDQm as a proxy to a PDQ environment.

IHE PIXm 3.1.0 and PDQm 3.2.0; Microsoft Learn, $convert-data (August 2026); Google Cloud, HL7v2 concepts; project READMEs, read November 2026.

Request paths from the specifications. Named examples from IHE PIXm and PDQm and from each product’s documentation, read November 2026.

Asking the source needs a v2 query interface, which IHE describes only for identity. Converting on the way through produces one bundle per message and leaves the store to someone else: Microsoft says its default $convert-data templates are not intended for production. So most fronts build from the feed, and so does the FHIR Front.

What HL7’s v2-to-FHIR guide gives you

HL7 Version 2 to FHIR reached STU 1 in October 2025. It maps messages, segments, data types and code tables to FHIR R4 as 263 ConceptMaps a program can read, and calls itself “a starting point for implementations”. Every page is informative, and Z-segments “will not be considered for inclusion”.

What the guide maps

Read 2026-11-04

HL7’s v2-to-FHIR guide, counted from its published package. Pick an everyday event to see whether the guide maps it and what it creates.

Maps in the guide
263
Message structures
13
Segments
75
and 105 data types
Code rows without a FHIR code
219
of 2,496, across 70 code tables

Event

Message structure
ADT_A01
Message map
In the guide
Encounter.status
unknown

Resources the map creates

  • MessageHeader
  • Provenance
  • Patient
  • Account
  • Observation
  • CareTeam
  • RelatedPerson
  • Encounter
  • Basic
  • Coverage
  • AllergyIntolerance
  • Condition
  • EpisodeOfCare
  • Procedure

Shares ADT_A01 with admit and register. The guide’s table sets Encounter.status to unknown for it.

hl7.fhir.uv.v2mappings 1.0.0 (STU 1) and HL7 table 0354 from hl7.terminology.r4 6.5.0, read by scripts/read-v2-fhir-coverage.mjs.

Counted from the guide’s published package (hl7.fhir.uv.v2mappings 1.0.0) and HL7 table 0354 by a committed script.

Two everyday events have no message map: a discharge (A03) and a merge (A40). And 219 of the 2,496 code rows have no FHIR code. The FHIR Front starts from the guide and adds maps of its own where it has none.

From a stream of events to current state

A v2 feed sends events. A FHIR server holds state. The guide maps one message at a time and leaves existing resources to the implementer, so most of the work in a front is here. Try it: an update (A08) after an admission.

Events into state

The guide’s own tables

A v2 feed sends events; a FHIR server holds state. Build a sequence and compare the guide’s status table applied as it stands with a front that keeps state.

Resource

Add a message (5 of 8)

Status after each message, applied two ways
#MessageGuide’s table, as it standsKept as state
1A01 Admitin-progressin-progress
2A08 Update patientunknownin-progressDiffers
3A02 Transferin-progressin-progress
4A08 Update patientunknownin-progressDiffers
5A03 Dischargefinishedfinished

2 of 5 steps differ. The only rule added: an update (A08) does not say where the patient is in the visit, so a front keeps the status it had. The guide’s row sets unknown, which FHIR calls “a value of last resort”.

hl7.fhir.uv.v2mappings 1.0.0: ConceptMaps table-hl70003-to-encounter-status and table-hl70085-to-observation-status, every row, read by scripts/read-v2-fhir-coverage.mjs. FHIR R4 encounter-status.

Every row of the guide’s two status tables, read from its package. The kept-state column adds one rule per resource, stated under the table.

Repetition is the other half. v2’s control chapter says “only the use of sequence numbers can prevent duplicate transactions”, and they are optional. FHIR’s conditional update, a PUT addressed by an identifier, makes a repeated message harmless; it is trial use in R4. And the acknowledgement is a promise: send it only once the message is stored.

When to acknowledge

Structure

In v2, a commit accept tells the sender it no longer has to resend. The same failure, played through two orderings.

  1. 1SourceSends ORU^R01, control id 4417
  2. 2FrontWrites the message to durable storage
  3. 3FrontReturns CA (commit accept), echoing 4417
  4. 4FrontRestarts before mapping (failure)
  5. 5FrontOn restart, maps the stored message
Safe

Nothing is lost. The message was stored before the source was told it could forget it.

HL7 v2 control chapter, acknowledgement rules (v2+ draft text): with a positive accept acknowledgement “the receiving system commits the message to safe storage in a manner that releases the sending system from the need to resend the message.”

The rule from HL7’s v2 control chapter; the failure is illustrative.

The FHIR Front keeps current state and acknowledges a message once it is stored (Phase 1).

Identifiers and codes on the way in

US Core requires every Patient identifier to carry a system URL. The guide sets it only for authorities in HL7’s identifier registry, so a hospital’s own record number gets assigner and no system, and fails US Core. Microsoft’s converter fills the gap with a dummy URL “to be replaced … by the end users”. The fix is a table the front owns: one URL per assigning authority.

The guide maps the merge segment only to Account, and none of its maps writes Patient.link. Merges, and local codes, are covered in Terminology and patient identity services. The FHIR Front configures a system URL per authority and links merged records (Phase 1), and applies your code maps (Phase 2).

What the API can and cannot answer

A front built from a feed knows what was sent after it started listening. History has to be replayed from the interface engine’s archive, and the arithmetic is worth doing early.

Loading history

Your numbers

A front built from a feed starts empty. Enter your own volumes to see how big a replay is, how long it takes, and how much of the window a caller wants the API holds without one. The starting values are examples, not typical figures.

20,000
1,000500,000
365
30 days10 years
100
52,000

Measure this on your own front: it depends on the maps, the store and the hardware.

30
Just started10 years
Messages to replay
7,300,000
a day’s volume × days of history
Replay time
20.3 h
backlog ÷ processing rate, end to end
Window held without a replay
8%
30 of 365 days

Arithmetic only. Messages are replayed in order through the same path as live ones, so the rate is the front’s own, not the archive’s.

Arithmetic on your own numbers. The starting values are examples, not typical figures.

US Core says what a server has to support. Appointment is not in it, and the SHALL on creating a DiagnosticReport applies only to reports and notes, not laboratory results.

What US Core asks of a server

Read 2026-11-04

For each resource a v2 feed fills, what the US Core server CapabilityStatement says a server SHALL support. Certification requires 6.1.0; 9.0.0 is the newest version it allows.

Version

Patient

In US Core

Interactions, SHALL

  • search-type
  • read

Searches, SHALL

  • _id
  • identifier
  • name
  • birthdate + name
  • gender + namethis version only

US Core Patient also requires identifier.system on every identifier, which a local record number does not get from the v2-to-FHIR guide alone.

US Core server CapabilityStatement, hl7.fhir.us.core 6.1.0 and 9.0.0 from packages2.fhir.org, read by scripts/read-us-core-searches.mjs.

The US Core server CapabilityStatement, 6.1.0 and 9.0.0, read from the packages by a committed script.

Say all of this in the CapabilityStatement, which FHIR: the API is the easy part explains, and point every resource at its message with a Provenance, as the guide suggests. Authorization is the front’s to provide, since the source has no idea who is asking; An AI agent is a client, not a user covers scopes. The FHIR Front authorizes every request with SMART Backend Services and replays archives (Phase 1).

Testing a front on your own feed

HL7 publishes test messages and no tool to check a conversion: it “has no plans to either create, nor certify any transform validator at this time.”

Testing a front

0 of 4 checks

HL7 provides test messages and no tool to check a conversion. Four checks cover most of it. Tick them off for your own front; nothing is stored.

  1. Passing proves
    The resources are shaped the way US Core says, with codes from the right value sets.
    It does not prove
    That a value is the right one for the patient. A valid Observation can carry the wrong result.

    A front built from the guide alone fails first on Patient.identifier.system.

  2. Passing proves
    Admissions, discharges and results received match encounters and observations held, so nothing was dropped.
    It does not prove
    That what was kept is current. Counts match on a store full of stale statuses.

    HL7’s guide names the risk: “separate V2 and FHIR worlds will be out of step”.

  3. Passing proves
    The same messages in the same order give the same resources, so a bad map can be fixed and rerun.
    It does not prove
    That the order the feed sent was the order things happened.

    Without it, a wrong map can only be patched, never repaired.

  4. Passing proves
    State survives what live feeds do: updates, cancels, corrections, merges and repeats.
    It does not prove
    That every local variation is covered. Your feed has its own.
    Cases sent (0 of 7)

HL7 Version 2 to FHIR 1.0.0, Validation page: test messages with their bundles, and no transform validator. The HL7 v2 Message Creator sends the hard cases to a system under test.

Four checks, what each proves and what it does not. Ticks are kept only for this visit.

The HL7 v2 Message Creator sends those cases to a system under test, and the FHIR Front’s mapping workbench shows the rule behind each element (Phase 1).

Where the standards stop

Transport and field mappings are standardised. How a front keeps state, how current it is and how it loads history are not.

Writing back is further out: HL7’s guide maps one way, and no specification turning a FHIR order into a v2 order was found. The FHIR Front does not plan it. Notifications are nearer, through HL7’s Subscriptions R5 Backport (Phase 2).

Elsewhere the pattern holds and the levers differ. Ontario’s laboratory system publishes a v2 interface and a view-only FHIR R4 guide; Canada’s CA Core+ is still a draft, so the FHIR Front leaves it to Phase 2.

Questions

Request access

Tell us which system you would put it in front of and which FHIR resources you would need first. If it fits, the reply includes access to the Phase 1 beta.

About: FHIR Front for HL7 v2 Systems

What would you like?

For example: PACS or RIS vendor, HL7 version, operating system.

Working on one of these problems?

Tell us what you’re working on in interoperability, data platforms, or clinical AI, and we’ll tell you what we think.

Get in touch