# Laborergebnisse in einen FHIR-Datensatz importieren

> Tutorial: Importieren Sie einen Laborbericht als CSV und als HL7 v2 ORU^R01 in FHIR R4 Observations mit LOINC-Codes und Referenzbereichen, behandeln Sie nicht zugeordnete Marker und erneut gesendete Berichte und verfolgen Sie jedes Ergebnis zu seinem Labor.

Source: https://developers.anpheros.com/de/guides/import-lab-results-fhir

**Dieses Tutorial nimmt einen Laborbericht als CSV-Datei und als HL7 v2 ORU^R01-Nachricht, importiert ihn jeweils in einem Request in den HL7 FHIR R4-Datensatz eines Patienten und zeigt, was Sie zurückbekommen: Labor-`Observation`-Ressourcen mit LOINC-Codes, Referenzbereichen und Herkunft.** Es behandelt auch die beiden Probleme, auf die jede Laborintegration stößt: Marker, die nicht automatisch zugeordnet werden können, und Berichte, die doppelt gesendet werden. Alles läuft auf der kostenlosen Sandbox mit einem synthetischen Patienten.

## Warum Laborergebnisse schwer zu speichern sind

Ein Laborbericht erscheint einfach: ein Marker, ein Wert, eine Einheit, ein Referenzbereich, ein Datum. In der Praxis benennt jedes Labor Marker auf seine eigene Weise ("Hemoglobina glicozilata", "HbA1c", "Glycated haemoglobin"), verwendet Kommas oder Punkte für Dezimalstellen, schreibt Bereiche als `4,0-5,6`, `<5` oder `>3.5` und sendet denselben Bericht erneut, wenn etwas fehlschlägt. Als Freitext gespeichert, können diese Ergebnisse nicht über die Zeit verglichen, grafisch dargestellt, mit einer anderen Anwendung geteilt oder mit Zuversicht an ein KI-Modell übergeben werden.

Ein FHIR-Datensatz speichert jedes Ergebnis als `Observation` mit einem LOINC-Code, einer UCUM-Einheit, einem Wert, einem Referenzbereich und einem Datum und speichert, wer es gesendet hat, in einer `Provenance`-Ressource. Der [Labor-Konnektor](https://developers.anpheros.com/de/guides/lab-connector) übernimmt diese Konvertierung für Sie.

```
 lab report (CSV, HL7 v2, JSON)
        │  POST /v1/patients/{id}/labs/import
        ▼
 ┌──────────────────────────────────────────────┐
 │ parse rows → map marker to LOINC → parse     │
 │ value, unit, range → stable id per row       │
 └──────────────────────────────────────────────┘
        │
        ▼
 Observation (category laboratory) + Provenance (author_type import, source system, report id)
        │
        ├─► the patient's app and every app they consented to
        └─► webhooks: resource.created per Observation
```

## Bevor Sie beginnen

Sie benötigen einen Sandbox-Schlüssel (`sk_test_…`) von [platform.anpheros.com/dashboard](https://platform.anpheros.com/dashboard/) (**Sandbox-Schlüssel erhalten**). Die Beispiele verwenden `curl`; die [SDKs](https://developers.anpheros.com/de/guides/sdks) haben die gleichen Aufrufe (`labs.importCsv`, `labs.importHl7`, `labs.importItems`).

```bash
export BASE=https://platform.anpheros.com
export KEY=sk_test_…
# Elena Ionescu, a synthetic patient with type 2 diabetes
export PID=$(curl -s "$BASE/fhir/R4/Patient?identifier=https://anpheros.com/fhir/sid/sandbox-persona|p02" \
  -H "Authorization: Bearer $KEY" | jq -r '.entry[0].resource.id')
```

## Schritt 1: CSV-Bericht importieren

So könnte ein rumänisches Labor einen Bericht exportieren: Semikolons, Dezimalkommas, rumänische Spaltennamen und Daten als `DD.MM.YYYY`. Der Connector erkennt rumänische und englische Spaltennamen.

```bash
cat > report.csv <<'EOF'
Analiza;Rezultat;UM;Interval de referinta;Data
Hemoglobina glicozilata (HbA1c);6,9;%;4,0-5,6;01.10.2026
Glicemie;131;mg/dL;70-100;01.10.2026
TSH;2,1;mUI/L;0,4-4,0;01.10.2026
Marker foarte rar;12;U/L;0-20;01.10.2026
EOF

curl -X POST "$BASE/v1/patients/$PID/labs/import" -H "Authorization: Bearer $KEY" \
     -H "Content-Type: text/csv" -H "X-Anpheros-Source-System: labx" \
     -H "Idempotency-Key: report-2026-10-01-elena" --data-binary @report.csv
```

Die Antwort (`201`):

```json
{"created": 4, "skipped": 0, "unmapped": ["Marker foarte rar"], "warnings": [],
 "observations": [
  {"id": "ff0bbb44-…", "marker": "Hemoglobina glicozilata (HbA1c)", "code": "4548-4", "system": "http://loinc.org", "value": 6.9, "unit": "%", "date": "2026-10-01"},
  {"id": "ebe5522f-…", "marker": "Glicemie", "code": "2345-7", "system": "http://loinc.org", "value": 131.0, "unit": "mg/dL", "date": "2026-10-01"},
  {"id": "bace44a8-…", "marker": "TSH", "code": "3016-3", "system": "http://loinc.org", "value": 2.1, "unit": "mUI/L", "date": "2026-10-01"},
  {"id": "26fd2270-…", "marker": "Marker foarte rar", "code": "marker_foarte_rar", "system": "urn:anpheros:lab-code", "value": 12.0, "unit": "U/L", "date": "2026-10-01"}]}
```

HbA1c, Glukose und TSH wurden anhand ihrer Namen LOINC zugeordnet. Die Dezimalkommas wurden zu Zahlen, und die Bereiche wurden zu `referenceRange`. Eine Zeile kam in `unmapped` zurück. Sie wird immer noch unter dem eigenen Code des Labors (`urn:anpheros:lab-code`) mit dem exakten Text aus dem Bericht gespeichert, sodass nichts verloren geht.

## Schritt 2: Unzugeordnete Marker behandeln

Einige Namen erfordern eine Entscheidung. "Glicemie" (Blutzucker) ist ein gutes Beispiel: LOINC hat einen Code für Glukose in Serum oder Plasma (`2345-7`, eine im Labor entnommene Venenprobe) und einen anderen für Glukose in Vollblut (`2339-0`, z. B. ein Fingerstich). Auf einem Laborbericht wird ein einfaches "Glicemie" Serum oder Plasma zugeordnet. Ein Name, der "capilar", "capillary" oder "sânge integral" angibt, wird Vollblut zugeordnet:

```json
{"created": 1, "skipped": 0, "unmapped": [], "warnings": [],
 "observations": [{"id": "00480a6d-…", "marker": "Glicemie capilara", "code": "2339-0", "system": "http://loinc.org", "value": 140.0, "unit": "mg/dL", "date": "2026-10-02"}]}
```

Suchen Sie für Marker, die der Connector nicht erkennt, den Code nach:

```bash
curl "$BASE/v1/terminology/loinc?q=glucose" -H "Authorization: Bearer $KEY"
```

```json
{"data": [
  {"system": "http://loinc.org", "code": "2339-0", "display": "Glucose [Mass/volume] in Blood", "display_ro": "Glicemie (sânge)", "category": "laboratory", "unit": "mg/dL"},
  {"system": "http://loinc.org", "code": "2345-7", "display": "Glucose [Mass/volume] in Serum or Plasma", "display_ro": "Glicemie (ser)", "category": "laboratory", "unit": "mg/dL"}],
 "total": 2}
```

Senden Sie den Code dann in einer Spalte `LOINC`. Ein Code im Bericht hat immer Vorrang vor dem Namen. Behalten Sie diese Zuordnung pro Labor auf Ihrer Seite bei und fügen Sie die Spalte zu jedem Bericht von diesem Labor hinzu:

```
Analiza;Rezultat;UM;Interval de referinta;Data;LOINC
Glicemie;99;mg/dL;70-100;04.10.2026;2339-0
```

Marker, die LOINC überhaupt nicht abdeckt, wie der erfundene "Marker foarte rar", können unter dem Code des Labors verbleiben. Sie werden dem Patienten angezeigt und in den Datensatz aufgenommen. Sie können nicht mit den Ergebnissen anderer Labore verglichen werden.

## Schritt 3: Senden Sie denselben Bericht zweimal

Labore senden Berichte erneut. Jede Zeile erhält eine stabile Kennung, die aus der Berichts-ID, dem Code, dem Datum und dem Wert aufgebaut ist, sodass ein zweiter Import desselben Berichts nichts Neues erzeugt:

```json
{"created": 0, "skipped": 4, "unmapped": ["Marker foarte rar"], "warnings": [], "observations": []}
```

Geänderte Zeilen, zum Beispiel ein korrigierter Wert, werden als neue Ergebnisse importiert. Der `Idempotency-Key`-Header bietet eine zweite Garantie: Ein Netzwerk-Retry mit demselben Schlüssel gibt die erste Antwort unverändert zurück.

## Schritt 4: Importieren einer HL7 v2 ORU^R01-Nachricht

Die meisten Laborinformationssysteme sprechen HL7 v2. Senden Sie die Nachricht, wie sie ist (ER7-Text, Segmente getrennt durch CR oder LF):

```
MSH|^~\&|LABX|LAB1|ANPHEROS|EHR|202610010930||ORU^R01|MSG00077|P|2.5.1
PID|1||12345||Ionescu^Elena||19850903|F
OBR|1||R-77|24331-1^Lipid panel^LN|||202610010800
OBX|1|NM|2093-3^Cholesterol [Mass/volume] in Serum or Plasma^LN||212|mg/dL|<200|H|||F|||202610010800
OBX|2|NM|2085-9^HDL Cholesterol^LN||52|mg/dL|>40|N|||F|||202610010800
```

```bash
curl -X POST "$BASE/v1/patients/$PID/labs/import" -H "Authorization: Bearer $KEY" \
     -H "Content-Type: x-application/hl7-v2+er7" --data-binary @oru.hl7
```

```json
{"created": 2, "skipped": 0, "unmapped": [], "warnings": [],
 "observations": [
  {"id": "b562045b-…", "marker": "Cholesterol [Mass/volume] in Serum or Plasma", "code": "2093-3", "system": "http://loinc.org", "value": 212.0, "unit": "mg/dL", "date": "2026-10-01T08:00:00Z"},
  {"id": "9b3274e4-…", "marker": "HDL Cholesterol", "code": "2085-9", "system": "http://loinc.org", "value": 52.0, "unit": "mg/dL", "date": "2026-10-01T08:00:00Z"}]}
```

`OBX-3` mit dem `LN`-Codierungssystem wird direkt als LOINC verwendet. `OBX-7` wird zum Referenzbereich und `OBX-8` (`H`, `N`) zur Interpretation. `OBR-3` (`R-77`) wird als Berichts-ID in der Provenienz beibehalten. Der Patient ist derjenige in der URL: das `PID`-Segment wird nicht zur Patientensuche verwendet, daher kann eine falsche `PID` keine Ergebnisse an eine andere Person anhängen.

Halten Sie bereits geparste Ergebnisse vor? Senden Sie JSON: `{"date": "2026-10-01", "origin": "report-77", "items": [{"marker": "Ferritin", "value": 38, "unit": "ng/mL", "ref_low": 15, "ref_high": 150}]}`. Ferritin wird LOINC `2276-4` zugeordnet.

## Schritt 5: Ergebnisse als FHIR lesen

```bash
curl "$BASE/fhir/R4/Observation?patient=$PID&code=http://loinc.org|4548-4&_sort=-date&_count=1" \
     -H "Authorization: Bearer $KEY"
```

Der importierte HbA1c, wie er gespeichert ist:

```json
{
  "resourceType": "Observation",
  "id": "62b1b0c0-…",
  "meta": {"versionId": "1", "lastUpdated": "2026-10-12T20:05:57.011Z"},
  "identifier": [{"system": "urn:anpheros:lab-import", "value": "c52d3cd6449291d34f6bef1516d0ac05"}],
  "status": "final",
  "category": [{"coding": [{"system": "http://terminology.hl7.org/CodeSystem/observation-category", "code": "laboratory"}]}],
  "code": {"coding": [{"system": "http://loinc.org", "code": "4548-4", "display": "Hemoglobin A1c/Hemoglobin.total in Blood"}],
           "text": "Hemoglobina glicozilata (HbA1c)"},
  "subject": {"reference": "Patient/…"},
  "effectiveDateTime": "2026-10-01",
  "valueQuantity": {"value": 6.9, "unit": "%"},
  "referenceRange": [{"low": {"value": 4.0, "unit": "%"}, "high": {"value": 5.6, "unit": "%"}}]
}
```

Die LOINC-Anzeige ist der Standardname in englischer Sprache. `code.text` behält die eigene Formulierung des Labors bei, sodass der Patient weiterhin sieht, was auf dem Papierbericht stand. Weitere Informationen zu Ressourcen und Suchen finden Sie im Leitfaden zur [FHIR-Plattform](https://developers.anpheros.com/de/guides/fhir) und zu [FHIR-Codesystemen](https://developers.anpheros.com/de/guides/fhir-code-systems).

## Schritt 6: Überprüfen, wer es gesendet hat

```bash
curl "$BASE/v1/patients/$PID/provenance/Observation/62b1b0c0-…" -H "Authorization: Bearer $KEY"
```

```json
{"data": [{"version": 1, "activity": "CREATE", "recorded": "2026-10-12T20:05:57.011000Z",
           "author_type": "import", "author": "proj_…", "source_system": "labx", "origin_id": null,
           "fhir": "Provenance/f15c4fee-…"}], "total": 1}
```

`author_type: import` und `source_system: labx` bleiben mit dem Wert erhalten. Wenn eine KI-Anwendung dieses Ergebnis später über die [Kontext-API](https://developers.anpheros.com/de/guides/llm-healthcare-data) liest, wird es als `[import/labx]` gekennzeichnet, damit das Modell ein Laborergebnis von einem vom Patienten eingegebenen Wert unterscheiden kann.

## Was passiert als Nächstes

- Der Patient sieht die Ergebnisse in seiner App. Jede Anwendung, der er zugestimmt hat, kann sie lesen, innerhalb ihrer Scopes ([Consent- und Zugriffsmodell](https://developers.anpheros.com/de/guides/consent)).
- Ein `resource.created` [Webhook](https://developers.anpheros.com/de/guides/webhooks) wird für jede Observation ausgelöst, sodass ein Klinik-Dashboard oder eine KI-Zusammenfassung ohne Polling aktualisiert werden kann.
- `POST /fhir/R4/Observation/$validate?profile=eu-lab` berichtet, wie ein Ergebnis mit dem HL7 Europe Laboratory Report Profile verglichen wird.
- Bis zu 500 Zeilen pro Anfrage; Limits sind in [Limits und Ratenlimits](https://developers.anpheros.com/de/guides/limits) aufgeführt.

## Häufig gestellte Fragen

### Welche Laborberichtformate können in FHIR importiert werden?
CSV mit einer Kopfzeile (Komma, Semikolon oder Tabulator, Dezimalkomma akzeptiert), HL7 v2 ORU^R01-Nachrichten und JSON. PDF-Berichte können als Dokumente gespeichert werden; aus ihnen extrahierte Werte verweisen auf das Dokument zurück.

### Was passiert mit Markern ohne LOINC-Code?
Sie werden unter dem eigenen Code des Labors mit dem exakten Text aus dem Bericht gespeichert und in `unmapped` aufgeführt. Fügen Sie für dieses Labor eine LOINC-Spalte hinzu, und sie werden zugeordnet. Ein Code im Bericht hat immer Vorrang vor dem Namen.

### Ist es sicher, einen Bericht erneut zu senden?
Ja. Jede Zeile hat eine stabile Kennung, die aus dem Bericht, dem Code, dem Datum und dem Wert aufgebaut ist, sodass bereits importierte Zeilen übersprungen werden; geänderte Zeilen werden als neue Ergebnisse importiert.

### Kann ein Labor Ergebnisse für jeden Patienten importieren?
Nein. Ein Labor importiert in Patienten, die sein Projekt erstellt hat oder deren Datensätze die Person über OAuth mit ihm geteilt hat. Andere Patienten existieren für es nicht (`404`).

## Verwandt

- [Laboratory results API](https://developers.anpheros.com/de/guides/lab-results-api): HL7 v2 und FHIR nebeneinander und was ein Ergebnis enthalten muss
- [Lab connector](https://developers.anpheros.com/de/guides/lab-connector): jede Spaltenbezeichnung, jedes HL7-Feld und jedes Antwortfeld
- [Healthcare data interoperability](https://developers.anpheros.com/de/guides/interoperability): warum Codes und Herkunftsaussagen ausgetauschte Daten nutzbar machen
- [Healthcare integrations](https://developers.anpheros.com/de/guides/healthcare-integrations): Kliniken, Labore, Geräte und Drittanbieter-Apps
- [Medical data API](https://developers.anpheros.com/de/guides/medical-data-api): Schreiben einzelner Beobachtungen, Zustände und Medikationen
- [How to build an AI healthcare app with a FHIR backend](https://developers.anpheros.com/de/guides/build-ai-healthcare-app): Verwendung dieser Ergebnisse in einer KI-Antwort
