# HL7 v2 and FHIR for clinical dashboards

> From an HL7 v2 ORU^R01 lab message to a dashboard tile: FHIR Observations with ranges and flags, signed webhooks, no duplicates — and why this is not bedside monitoring.

Source: https://developers.anpheros.com/guides/clinical-dashboard-hl7-fhir

**A clinical dashboard needs results as structured, coded data the moment they are reported — test, value, unit, reference range and flag — not PDFs it has to read.** Laboratories still send most results as HL7 v2 ORU^R01 messages, while dashboards are easiest to build on FHIR R4 Observations. Anpheros sits between the two: a laboratory system posts the HL7 v2 message (or a CSV or JSON report) over HTTPS, each result becomes a FHIR Observation with its code (LOINC when the lab sends it), value and reference range, and a signed webhook tells your dashboard that new results arrived.

<!-- visual:dashboard-pipeline -->

## What the dashboard receives

Each OBX segment of the message becomes one laboratory Observation:

| HL7 v2 OBX field | FHIR R4 Observation | On the dashboard |
|---|---|---|
| OBX-3 test code | `code` (LOINC when the lab sends it; a local code is kept as the lab's code) | Test name; LOINC makes it comparable across labs |
| OBX-5 value, OBX-6 unit | `valueQuantity` (UCUM unit) | The number and its unit |
| OBX-7 reference range | `referenceRange` | The normal band |
| OBX-8 abnormal flag | `interpretation` (H, L, …) | The red or blue flag |
| OBX-14 time | `effectiveDateTime` | When the sample was taken |

<!-- visual:dashboard-mock -->

## Import a message and react to it

Send the message for a patient you created (or one you hold a grant for):

```ts
import { readFile } from 'node:fs/promises';
import { Anpheros, apiKey } from '@anpheros/sdk';

const anpheros = new Anpheros({ auth: apiKey(process.env.ANPHEROS_KEY!) });   // a sandbox key, sk_test_…
const message = await readFile('oru_r01.hl7', 'utf8');
const result = await anpheros.labs.importHl7(patientId, message, { sourceSystem: 'lab-lis' });
console.log(result);   // created, skipped and unmapped counts
```

Then let the platform call your dashboard backend instead of polling it:

```ts
await anpheros.webhooks.create('https://dashboard.example.org/anpheros/hook', { events: ['resource.created'] });
```

Each delivery is signed (verify it with `verifyWebhookSignature` from the SDK) and retried if your server does not answer. The event carries the resource type, id and patient; read the new Observations and refresh the tile. Resent reports are skipped, so a laboratory that retransmits on a timeout does not create duplicate rows on the screen.

## Choosing HL7 v2 or FHIR for each link

| Link | Use | Why |
|---|---|---|
| Laboratory → data layer | HL7 v2 ORU^R01 (or CSV/JSON) | What laboratory systems already emit; no change on their side |
| Data layer → dashboard | FHIR R4 Observation + webhooks | Coded, versioned JSON your front end can read directly |
| Dashboard → other apps | FHIR R4, under the patient's consent | One standard for every consumer |

## What this is not

- **Not a bedside monitor feed.** Anpheros accepts laboratory reports over HTTPS. It does not receive continuous waveforms or device streams from intensive care monitors, and it is not an alarm system: alerts that affect care need a certified clinical system.
- **Not an MLLP interface engine.** Messages arrive over HTTPS; if your laboratory only speaks MLLP over TCP, an interface engine in front forwards them.
- **One HL7 v2 message type.** ORU^R01 laboratory results are accepted; orders (ORM/OML) and ADT messages are not.

## Frequently asked questions

### Can a dashboard read HL7 v2 lab results directly?
It can, but every dashboard then needs its own HL7 v2 parser, code mapping and de-duplication. Converting once into FHIR R4 Observations with LOINC codes gives every screen the same clean data.

### How fast do imported results reach the dashboard?
The import request returns when the Observations are stored, and a `resource.created` webhook is queued for each of them at the same time. Delivery is retried if your endpoint is unavailable.

### How are abnormal results flagged?
OBX-8 becomes the Observation's `interpretation` (for example H or L) and OBX-7 its `referenceRange`, so the dashboard can show both the flag and the normal band.

### Does Anpheros support ICU monitoring?
No. It stores laboratory and clinical results and notifies your systems about new data; continuous bedside monitoring and clinical alarms stay with certified medical devices.

<!-- visual:cta-dashboard -->

## 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)
- [Lab connector](https://developers.anpheros.com/guides/lab-connector): the endpoint reference
- [FHIR vs HL7 v2: practical differences](https://developers.anpheros.com/guides/fhir-vs-hl7-v2)
- [Remote patient monitoring with FHIR](https://developers.anpheros.com/guides/remote-patient-monitoring-fhir)
- [Webhooks](https://developers.anpheros.com/guides/webhooks)
