# FHIR vs HL7 v2: practical differences

> HL7 v2 messages and FHIR resources compared for developers: format, transport, the same lab result in both, translation pitfalls, and where Anpheros accepts v2.

Source: https://developers.anpheros.com/guides/fhir-vs-hl7-v2

**HL7 v2 is the message format hospital systems have exchanged since the late 1980s — pipe-delimited events such as "patient admitted" or "lab result ready" pushed between systems over a network connection — while HL7 FHIR is a web API standard where applications read and write resources such as Patient and Observation over HTTPS in JSON.** They are not alternatives you pick once: most hospitals still run on v2 internally, new applications and patient-facing APIs use FHIR, and integration work is often translating one into the other. This page compares them on the points that matter when you write code, shows the same data in both, and explains where Anpheros accepts v2.

## Side by side

| | HL7 v2 | HL7 FHIR R4 |
|---|---|---|
| Style | Messages triggered by events (admit, order, result) | Resources you create, read, update, search |
| Format | Text segments separated by line breaks, fields by `\|`, components by `^` | JSON (or XML) |
| Transport | Usually MLLP over TCP inside the hospital network | HTTPS REST |
| Query | Limited; systems mostly push | Search parameters, `_include`, history |
| Security | Network-level (VPN, private links) | OAuth 2.0 / SMART on FHIR, TLS, scopes |
| Flexibility | Many optional fields and local Z-segments; every interface is negotiated | Base resources plus profiles (US Core, IPS, European IGs) |
| Typical users | EHR, lab, radiology, billing systems inside a hospital | Apps, patient-access APIs, cross-organisation exchange, AI |

The most common v2 messages:

| Message | Meaning | Closest FHIR resources |
|---|---|---|
| ADT^A01, A03, A08 | Admit, discharge, update patient | `Patient`, `Encounter` |
| ORM / OML | Order a test | `ServiceRequest` |
| ORU^R01 | Result ready | `Observation`, `DiagnosticReport` |
| SIU | Scheduling | `Appointment` |
| MDM | Document | `DocumentReference` |

## The same lab result in both

An ORU^R01 result line (OBX segment):

```
OBX|1|NM|2093-3^Cholesterol^LN||212|mg/dL|<200|H|||F|||20261002074500
```

The same result as an HL7 FHIR R4 Observation, as Anpheros stores it after importing that message:

```json
{
  "resourceType": "Observation",
  "status": "final",
  "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "laboratory"}]}],
  "code": {"coding": [{"system": "http://loinc.org", "code": "2093-3", "display": "Cholesterol [Mass/volume] in Serum or Plasma"}], "text": "Cholesterol"},
  "effectiveDateTime": "2026-10-02T07:45:00Z",
  "valueQuantity": {"value": 212.0, "unit": "mg/dL"},
  "interpretation": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/v3-ObservationInterpretation", "code": "H"}]}],
  "referenceRange": [{"high": {"value": 200.0, "unit": "mg/dL"}}]
}
```

Field by field: OBX-3 becomes `code`, OBX-5 and OBX-6 become `valueQuantity`, OBX-7 `referenceRange`, OBX-8 `interpretation`, OBX-11 `status`, OBX-14 `effectiveDateTime`. HL7 publishes an official [HL7 Version 2 to FHIR](https://build.fhir.org/ig/HL7/v2-to-fhir/) implementation guide with mappings for segments, data types and vocabularies.

## Where translations go wrong

- **Time zones.** v2 timestamps such as `20261002074500` often carry no offset; you must know the sender's zone. FHIR requires a zone whenever a time is present. (Anpheros reads an unzoned v2 time as UTC; send the offset if you have it.)
- **Local codes.** Many labs put their own codes in OBX-3 instead of LOINC. A good translation keeps the local code and maps it to LOINC when it can, rather than dropping it.
- **Repeated sends.** v2 senders retransmit on timeouts. Without a stable identifier per result, a FHIR store fills with duplicates.
- **Optional everything.** The same field can be empty, repeated or used differently by two senders. Validate the FHIR side; the [FHIR R4 validator](https://developers.anpheros.com/tools/fhir-validator) shows what a translated resource is missing.
- **Corrections.** v2 result status `C` (corrected) should update the existing Observation and keep its history, not create a second one.

## When to use which

- **Inside a hospital, between existing systems:** v2 is usually what the systems speak. An integration engine routes and transforms messages.
- **Building an app, a patient-access API or anything that crosses organisations:** FHIR, with OAuth and consent.
- **Feeding AI or analytics:** FHIR, because it is queryable, coded and versioned.
- **Both:** the common real-world pattern — receive v2 from the lab or EHR, store FHIR, serve FHIR to applications.

## Where Anpheros fits

Anpheros stores patient records as FHIR R4 and accepts one HL7 v2 message type: **ORU^R01 lab results**, sent over HTTPS to the [lab connector](https://developers.anpheros.com/guides/lab-connector) (`POST /v1/patients/{id}/labs/import` with `Content-Type: x-application/hl7-v2+er7`). Each OBX becomes a laboratory Observation with LOINC code, reference range and interpretation; the report id is kept in provenance and resent reports are skipped. A corrected result (OBX-11 = `C`) with a new value is stored as a new Observation with status `amended`; the original stays as it was, so if your source sends corrections, mark the earlier Observation `entered-in-error` or update it through the FHIR API. A worked example is [Lab results API](https://developers.anpheros.com/guides/lab-results-api).

It does not accept other v2 messages (ADT, orders, scheduling), does not listen on MLLP and does not send v2. For those, an integration engine in front of Anpheros translates to FHIR and writes through the API.

## Frequently asked questions

### Is FHIR replacing HL7 v2?
Not soon. v2 remains the backbone inside most hospitals because it works and is built into existing systems. FHIR is growing around it — in apps, patient access and exchange between organisations — and the two coexist, often with translation between them.

### What is MLLP?
The Minimal Lower Layer Protocol: a simple way of framing v2 messages over a TCP connection, with start and end characters around each message and an acknowledgement (ACK) back. FHIR uses HTTPS instead.

### Can I convert HL7 v2 messages to FHIR automatically?
Mostly. HL7's v2-to-FHIR implementation guide gives standard mappings, and integration engines implement them. Expect manual work for local codes, Z-segments, time zones and how each sender uses optional fields.

### Does Anpheros accept HL7 v2?
Yes, for lab results: ORU^R01 messages posted over HTTPS to the lab connector become FHIR Observations. Other v2 message types and MLLP connections are not supported.

## Related

- [Lab results API: HL7 v2, FHIR and LOINC](https://developers.anpheros.com/guides/lab-results-api)
- [How to import laboratory results into a FHIR record](https://developers.anpheros.com/guides/import-lab-results-fhir)
- [Healthcare data interoperability](https://developers.anpheros.com/guides/interoperability)
- [DICOM vs FHIR: imaging data and clinical data](https://developers.anpheros.com/guides/dicom-vs-fhir)
- [FHIR platform](https://developers.anpheros.com/guides/fhir)
