# API dei risultati di laboratorio: HL7 v2, FHIR e LOINC

> Come i risultati di laboratorio viaggiano come dati HL7 v2 e FHIR, cosa deve contenere un singolo risultato e come ricevere referti di laboratorio in un record FHIR, con un esempio reale.

Source: https://developers.anpheros.com/it/guides/lab-results-api

**Un'API per i risultati di laboratorio fornisce i risultati di laboratorio come dati strutturati — codice del test, valore, unità, intervallo di riferimento, stato e ora — invece di un PDF, in modo che il software possa memorizzarli, confrontarli, tracciarli e condividerli.** Oggi tali dati viaggiano in tre forme: messaggi HL7 v2 ORU^R01 (ancora la spina dorsale tra laboratori e ospedali), risorse HL7 FHIR R4 `Observation` e `DiagnosticReport` (il formato delle API moderne) ed esportazioni CSV, JSON o PDF specifiche del laboratorio. Questa pagina spiega come i pezzi si incastrano, cosa deve contenere una buona API per i risultati di laboratorio e come ricevere dati di laboratorio nel record FHIR di un paziente con Anpheros.

## Chi scambia i risultati di laboratorio e in quale formato

| Da → a | Formato usuale oggi | Note |
|---|---|---|
| Laboratorio → sistema ospedaliero o clinico | HL7 v2 ORU^R01 (negli Stati Uniti spesso secondo la guida HL7 v2.5.1 Laboratory Results Interface) | Gli ordini vanno nella direzione opposta come messaggi ORM/OML |
| Laboratorio → agenzia di sanità pubblica | HL7 v2 electronic lab reporting, sempre più FHIR | Solo condizioni segnalabili |
| Sistema clinico → app per pazienti | FHIR R4 tramite un'API di accesso per pazienti | Negli Stati Uniti, gli EHR certificati espongono i risultati di laboratorio come FHIR (US Core); nell'UE lo European Health Data Space elenca i risultati di laboratorio tra le sue categorie di dati prioritarie |
| Laboratorio → paziente | Report PDF, portale, a volte CSV | Il formato che la maggior parte dei pazienti riceve effettivamente |
| App → modello AI | Contesto strutturato costruito da Observations | Richiede codici e unità per essere affidabile |

La direzione è importante: un sistema informativo di laboratorio (LIS) è la fonte autorevole per un risultato, e ogni sistema a valle ne conserva una copia. Ciò che rende attendibili le copie è che ognuna conserva il codice, l'unità, l'intervallo e l'origine del valore.

## Cosa deve contenere un singolo risultato di laboratorio

Un risultato che dice solo "Glucosio 126" non può essere interpretato in modo sicuro. Un risultato completo contiene:

- **Un codice standard.** LOINC identifica l'analita, il campione e il metodo: `2345-7` è glucosio in siero o plasma, `2339-0` è glucosio in sangue intero. Il codice proprio del laboratorio può viaggiare accanto ad esso.
- **Un valore con un'unità.** Idealmente un'unità UCUM (`mg/dL`, `mmol/L`, `10*3/uL`), in modo che i valori di due laboratori possano essere convertiti e confrontati.
- **Il range di riferimento** utilizzato dal laboratorio e un flag di **interpretazione** (H, L, N...) quando il laboratorio ne fornisce uno.
- **Stato:** preliminare, finale, corretto o modificato. Le correzioni accadono; un API deve permettere di vedere la nuova versione senza perdere quella vecchia.
- **Tempi:** quando il campione è stato raccolto (`effectiveDateTime`) e quando il risultato è stato rilasciato (`issued`).
- **Origine:** quale laboratorio lo ha prodotto e a quale referto o ordine appartiene.

In FHIR R4 ogni risultato è un `Observation` con `category = laboratory`, e il referto che li raggruppa è un `DiagnosticReport` che elenca le Osservazioni in `result`. Esempi validi di entrambi, con gli errori che i validatori segnalano più spesso, si trovano negli [esempi JSON FHIR R4](https://developers.anpheros.com/tools/fhir-examples/observation-lab-result) — vedere anche l' [esempio DiagnosticReport](https://developers.anpheros.com/tools/fhir-examples/diagnostic-report).

## HL7 v2 e FHIR affiancati

Lo stesso risultato di un pannello lipidico, come la maggior parte dei laboratori lo invia oggi e come un'API dovrebbe memorizzarlo:

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

| Campo HL7 v2 | Significato | Elemento Observation FHIR R4 |
|---|---|---|
| OBX-3 `2093-3^Cholesterol^LN` | Test, codificato in LOINC | `code.coding` (sistema `http://loinc.org`) |
| OBX-5 `212`, OBX-2 `NM` | Valore numerico | `valueQuantity.value` |
| OBX-6 `mg/dL` | Unità | `valueQuantity.unit` |
| OBX-7 `<200` | Intervallo di riferimento | `referenceRange.high` |
| OBX-8 `H` | Flag di anomalia | `interpretation` |
| OBX-11 `F` | Risultato finale | `status = final` |
| OBX-14 | Ora dell'osservazione | `effectiveDateTime` |

La conversione tra i due è principalmente una mappatura dei campi. Le parti difficili sono altrove: laboratori che inviano i propri codici invece di LOINC, numeri scritti come testo (`"6,4"`, `"<5"`), intervalli in diverse notazioni e report che vengono inviati nuovamente dopo un timeout. [Come normalizzare i dati medici](https://developers.anpheros.com/it/guides/normalize-medical-data) tratta questi argomenti in dettaglio.

## Ricezione dei risultati di laboratorio in un record FHIR con Anpheros

Anpheros memorizza il record di ogni paziente come HL7 FHIR R4 e dispone di un [connettore di laboratorio](https://developers.anpheros.com/it/guides/lab-connector): una richiesta accetta un intero report in formato HL7 v2, CSV o JSON e restituisce Observations di laboratorio con codici LOINC, intervalli di riferimento, interpretazione e provenienza.

```bash
curl -s -X POST "https://platform.anpheros.com/v1/patients/$PID/labs/import" \
  -H "Authorization: Bearer $KEY" \
  -H "Content-Type: x-application/hl7-v2+er7" \
  -H "X-Anpheros-Source-System: springfield-lis" \
  --data-binary @lipid-panel.hl7
```

Per un pannello lipidico a tre voci (colesterolo, HDL, trigliceridi), la risposta, da un'esecuzione locale della piattaforma, è:

```json
{
  "created": 3, "skipped": 0, "unmapped": [], "warnings": [],
  "observations": [
    {"id": "26ed9219-…", "marker": "Cholesterol", "code": "2093-3", "system": "http://loinc.org",
     "value": 212.0, "unit": "mg/dL", "date": "2026-10-02T07:45:00Z"},
    {"id": "2633d1d4-…", "marker": "HDL cholesterol", "code": "2085-9", "system": "http://loinc.org",
     "value": 48.0, "unit": "mg/dL", "date": "2026-10-02T07:45:00Z"},
    {"id": "a02520bb-…", "marker": "Triglyceride", "code": "2571-8", "system": "http://loinc.org",
     "value": 165.0, "unit": "mg/dL", "date": "2026-10-02T07:45:00Z"}
  ]
}
```

Ogni risultato memorizzato è una Observation FHIR R4 standard, leggibile da qualsiasi client FHIR:

```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"},
  "subject": {"reference": "Patient/4c3062d9-…"},
  "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"}}]
}
```

L'invio dello stesso messaggio più volte non crea nulla di nuovo (`"created": 0, "skipped": 3`): ogni riga ottiene un identificatore stabile dall'ID del report, dal codice, dalla data e dal valore. I marcatori che la piattaforma non riesce a mappare a LOINC mantengono il codice del laboratorio e ritornano in `unmapped`, in modo da poter correggere la mappatura alla fonte.

La lettura dei risultati è una ricerca FHIR standard:

```bash
curl -s "https://platform.anpheros.com/fhir/R4/Observation?patient=$PID&category=laboratory&code=http://loinc.org|2093-3" \
  -H "Authorization: Bearer $KEY"
```

Altri modi di ingresso e uscita degli stessi dati:

- **FHIR direttamente:** `POST /fhir/R4/Observation`, o un Bundle di transazione con il `DiagnosticReport` e le sue Observations insieme.
- **Eventi:** un [webhook](https://developers.anpheros.com/it/guides/webhooks) `resource.created` per Observation, in modo che una clinica o un'app possa reagire all'arrivo dei risultati.
- **Per persone e AI:** il paziente vede i risultati nella propria app; le applicazioni a cui acconsente li leggono; `POST /v1/context` fornisce a un modello AI un riepilogo etichettato per sorgente che include i valori di laboratorio recenti.
- **Provenienza:** ogni risultato importato registra `author_type = import`, il sistema sorgente e l'ID del report ([provenienza dei dati medici](https://developers.anpheros.com/it/guides/medical-data-provenance)).

La guida completa, con un report CSV, un messaggio HL7 v2, marcatori non mappati e report inviati nuovamente su un paziente sintetico, è il tutorial [Come importare risultati di laboratorio in un record FHIR](https://developers.anpheros.com/it/guides/import-lab-results-fhir).

## Controlla i risultati prima di inviarli

Il [validatore FHIR R4](https://developers.anpheros.com/tools/fhir-validator) gratuito controlla la struttura di un'Observation e i value set richiesti, e con il profilo `eu-lab` controlla anche ciò che un risultato di laboratorio dovrebbe contenere: la categoria `laboratory`, un codice LOINC, un soggetto, uno stato final-type, un'ora, un valore, un'unità UCUM e un intervallo di riferimento. Gli stessi controlli vengono eseguiti sulla piattaforma tramite `POST /fhir/R4/Observation/$validate?profile=eu-lab`.

## Scelta di un'API per i risultati di laboratorio: una checklist

- Memorizza i risultati come FHIR R4 Observations con codici LOINC, o come righe nel proprio schema?
- Può accettare i formati inviati dai vostri laboratori (HL7 v2 nella maggior parte degli ospedali, CSV o PDF da laboratori più piccoli)?
- Cosa succede a un marcatore che non riesce a mappare: viene rifiutato, scartato o mantenuto con il codice del laboratorio?
- I tentativi di nuovo invio sono sicuri, o un report inviato nuovamente crea duplicati?
- I risultati corretti sono versionati, con il valore precedente ancora leggibile?
- L'origine di ogni valore è registrata e visibile al paziente?
- Chi può leggere i risultati e questa decisione è basata sul consenso del paziente?

## Cosa Anpheros non fa

Anpheros non è un sistema informativo di laboratorio e non è collegato a reti di laboratori commerciali: il laboratorio, la clinica o l'app del paziente inviano il referto. Non instrada ordini di laboratorio, non legge referti PDF tramite questa API (l'app Anpheros Daily estrae i risultati da foto e PDF dal lato del paziente) e non interpreta clinicamente i risultati. Le unità vengono memorizzate così come il laboratorio le invia; la loro conversione in codici UCUM spetta al mittente, come descritto in [Come normalizzare i dati medici](https://developers.anpheros.com/it/guides/normalize-medical-data).

## Domande frequenti

### Cos'è un'API per i risultati di laboratorio?
Un'interfaccia che consente al software di inviare o ricevere risultati di laboratorio come dati strutturati — un test codificato, un valore con un'unità, un intervallo di riferimento, uno stato e un'ora — piuttosto che come documento. Le moderne API per i risultati di laboratorio utilizzano le risorse Observation e DiagnosticReport di HL7 FHIR R4; la maggior parte dei laboratori emette ancora messaggi HL7 v2 ORU^R01.

### Quale sistema di codifica identifica i test di laboratorio?
LOINC. Ogni codice LOINC denomina l'analita, il campione e spesso il metodo, quindi `2345-7` (glucosio nel siero o nel plasma) e `2339-0` (glucosio nel sangue intero) sono risultati diversi. Le unità sono meglio espresse in UCUM.

### Qual è la differenza tra un Observation e un DiagnosticReport?
Un Observation è un singolo risultato, come il colesterolo 212 mg/dL. Un DiagnosticReport è il report nel suo complesso — il pannello che è stato ordinato, chi lo ha emesso e quando — e elenca i suoi Observation in `result`.

### Posso importare messaggi HL7 v2 di laboratorio in un server FHIR?
Sì. Ogni segmento OBX viene mappato a un Observation (OBX-3 a `code`, OBX-5 e OBX-6 a `valueQuantity`, OBX-7 a `referenceRange`, OBX-8 a `interpretation`). Il connettore di laboratorio Anpheros esegue questa operazione in una singola richiesta e conserva l'ID del report del laboratorio in Provenance.

### Come evito risultati di laboratorio duplicati quando un report viene reinviato?
Assegna a ogni risultato un identificatore stabile derivato dal report, dal test, dall'ora e dal valore, e salta le righe il cui identificatore esiste già. Il connettore di laboratorio Anpheros esegue questa operazione automaticamente e riporta il conteggio come `skipped`.

## Correlati

- [HL7 v2 to FHIR mapping](https://developers.anpheros.com/it/guides/hl7-v2-to-fhir-mapping): ogni segmento e campo OBX
- [How to import laboratory results into a FHIR record](https://developers.anpheros.com/it/guides/import-lab-results-fhir): il tutorial passo-passo
- [Lab connector](https://developers.anpheros.com/it/guides/lab-connector): il riferimento all'endpoint
- [How to normalize medical data](https://developers.anpheros.com/it/guides/normalize-medical-data): LOINC, UCUM, date, intervalli e duplicati
- [Medical data provenance explained](https://developers.anpheros.com/it/guides/medical-data-provenance)
- [FHIR code systems](https://developers.anpheros.com/it/guides/fhir-code-systems)
- [How to integrate clinic systems with a FHIR backend](https://developers.anpheros.com/it/guides/integrate-clinic-systems-fhir)
- [FHIR vs HL7 v2: practical differences](https://developers.anpheros.com/it/guides/fhir-vs-hl7-v2)
- [HL7 v2 and FHIR for clinical dashboards](https://developers.anpheros.com/it/guides/clinical-dashboard-hl7-fhir): da un messaggio di laboratorio a una tile del dashboard
