Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
Jak importować wyniki laboratoryjne do repozytorium FHIR
Samouczek: importuj raport laboratoryjny jako CSV i jako HL7 v2 ORU^R01 do FHIR R4 Observations z kodami LOINC i zakresami referencyjnymi, obsługuj niezmapowane markery i ponowne wysyłanie raportów, oraz śledź każdy wynik do jego laboratorium.
Ten samouczek przedstawia raport laboratoryjny w postaci pliku CSV oraz wiadomości HL7 v2 ORU^R01, importuje go do rekordu HL7 FHIR R4 pacjenta w jednym żądaniu dla każdego formatu i pokazuje, co otrzymasz w zamian: zasoby laboratoryjne Observation z kodami LOINC, zakresami referencyjnymi i pochodzeniem. Obejmuje również dwa problemy, z którymi boryka się każda integracja laboratoryjna: znaczniki, których nie można zmapować automatycznie, oraz raporty, które są wysyłane dwukrotnie. Wszystko działa na darmowym środowisku piaskownicy z syntetycznym pacjentem.
Dlaczego wyniki badań laboratoryjnych są trudne do przechowywania
Wynik badania laboratoryjnego wydaje się prosty: parametr, wartość, jednostka, zakres referencyjny, data. W praktyce każde laboratorium nazywa parametry na swój sposób („Hemoglobina glicozilata”, „HbA1c”, „Glycated haemoglobin”), używa przecinków lub kropek do zapisu dziesiętnego, zapisuje zakresy jako 4,0-5,6, <5 lub >3.5 i wysyła ten sam wynik ponownie, gdy coś się nie powiedzie. Przechowywane jako tekst swobodny, wyniki te nie mogą być porównywane w czasie, wykresowane, udostępniane innej aplikacji ani przekazywane modelowi AI z pewnością.
Rekord FHIR przechowuje każdy wynik jako Observation z kodem LOINC, jednostką UCUM, wartością, zakresem referencyjnym i datą, a także przechowuje informacje o tym, kto go wysłał w zasobie Provenance. Łącznik laboratoryjny wykonuje tę konwersję za Ciebie.
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
Zanim zaczniesz
Potrzebujesz klucza sandbox (sk_test_…) z platform.anpheros.com/dashboard (Uzyskaj klucz sandbox). Przykłady używają curl; SDK mają te same wywołania (labs.importCsv, labs.importHl7, labs.importItems).
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')
Krok 1: importowanie raportu CSV
Tak może wyglądać eksport raportu przez rumuńskie laboratorium: średniki, przecinki dziesiętne, rumuńskie nazwy kolumn i daty jako DD.MM.YYYY. Konektor rozpoznaje nazwy kolumn rumuńskie i angielskie.
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
Odpowiedź (201):
{"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, glukoza i TSH zostały zmapowane do LOINC na podstawie ich nazw. Przecinki dziesiętne zamieniły się w liczby, a zakresy stały się referenceRange. Jeden wiersz powrócił w unmapped. Jest on nadal przechowywany pod własnym kodem laboratorium (urn:anpheros:lab-code) z dokładnym tekstem z raportu, dzięki czemu nic nie zostało utracone.
Krok 2: obsługa niezmapowanych znaczników
Niektóre nazwy wymagają decyzji. "Glicemie" (glukoza we krwi) jest dobrym przykładem: LOINC ma jeden kod dla glukozy w surowicy lub osoczu (2345-7, próbka żylna pobrana w laboratorium) i inny dla glukozy w pełnej krwi (2339-0, na przykład z nakłucia palca). W raporcie laboratoryjnym sama nazwa "Glicemie" jest mapowana na surowicę lub osocze. Nazwa zawierająca "capilar", "capillary" lub "sânge integral" jest mapowana na pełną krew:
{"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"}]}
Dla znaczników, których konektor nie rozpoznaje, wyszukaj kod:
curl "$BASE/v1/terminology/loinc?q=glucose" -H "Authorization: Bearer $KEY"
{"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}
Następnie wyślij kod w kolumnie LOINC. Kod w raporcie zawsze ma pierwszeństwo przed nazwą. Zachowaj to mapowanie dla każdego laboratorium po swojej stronie i dodaj kolumnę do każdego raportu z niego:
Analiza;Rezultat;UM;Interval de referinta;Data;LOINC
Glicemie;99;mg/dL;70-100;04.10.2026;2339-0
Znaczniki, których LOINC w ogóle nie obejmuje, takie jak wymyślony "Marker foarte rar", mogą pozostać pod kodem laboratorium. Są one wyświetlane pacjentowi i włączane do dokumentacji. Nie można ich porównywać z wynikami innych laboratoriów.
Krok 3: wysłanie tego samego raportu dwukrotnie
Laboratoria wysyłają raporty ponownie. Każdy wiersz otrzymuje stabilny identyfikator zbudowany z identyfikatora raportu, kodu, daty i wartości, więc drugie zaimportowanie tego samego raportu niczego nie tworzy:
{"created": 0, "skipped": 4, "unmapped": ["Marker foarte rar"], "warnings": [], "observations": []}
Wiersze, które uległy zmianie, na przykład poprawiona wartość, są importowane jako nowe wyniki. Nagłówek Idempotency-Key dodaje drugą gwarancję: ponowna próba sieciowa z tym samym kluczem zwraca pierwszą odpowiedź bez zmian.
Krok 4: import wiadomości HL7 v2 ORU^R01
Większość systemów informatycznych laboratoriów komunikuje się w standardzie HL7 v2. Wyślij wiadomość w oryginalnym formacie (tekst ER7, segmenty oddzielone CR lub 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
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
{"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 z systemem kodowania LN jest używany bezpośrednio jako LOINC. OBX-7 staje się zakresem referencyjnym, a OBX-8 (H, N) interpretacją. OBR-3 (R-77) jest zachowywane jako identyfikator raportu w metadanych pochodzenia. Pacjentem jest ten z adresu URL: segment PID nie jest używany do wyszukiwania pacjenta, więc błędny PID nie może przypisać wyników do innej osoby.
Posiadasz już przetworzone wyniki? Wyślij JSON: {"date": "2026-10-01", "origin": "report-77", "items": [{"marker": "Ferritin", "value": 38, "unit": "ng/mL", "ref_low": 15, "ref_high": 150}]}. Ferrytyna jest mapowana na LOINC 2276-4.
Krok 5: Odczyt wyników jako FHIR
curl "$BASE/fhir/R4/Observation?patient=$PID&code=http://loinc.org|4548-4&_sort=-date&_count=1" \
-H "Authorization: Bearer $KEY"
Zaimportowane HbA1c, tak jak są przechowywane:
{
"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": "%"}}]
}
Nazwa LOINC to standardowa angielska nazwa. code.text zachowuje własne sformułowanie laboratorium, dzięki czemu pacjent nadal widzi to, co było na papierowym raporcie. Więcej informacji o zasobach i wyszukiwaniu można znaleźć w przewodniku po platformie FHIR oraz systemach kodowania FHIR.
Krok 6: Sprawdź, kto wysłał
curl "$BASE/v1/patients/$PID/provenance/Observation/62b1b0c0-…" -H "Authorization: Bearer $KEY"
{"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 i source_system: labx pozostają z wartością. Kiedy aplikacja AI odczyta później ten wynik za pomocą API kontekstu, zostanie on oznaczony jako [import/labx], dzięki czemu model będzie mógł odróżnić wynik laboratoryjny od wartości wprowadzonej przez pacjenta.
Co dalej
- Pacjent widzi wyniki w swojej aplikacji. Każda aplikacja, na którą wyraził zgodę, może je odczytać, w ramach swoich zakresów (model zgody i dostępu).
- Dla każdej obserwacji (Observation) uruchamiany jest webhook
resource.created, dzięki czemu pulpit kliniki lub podsumowanie AI może zostać zaktualizowane bez konieczności odpytywania. POST /fhir/R4/Observation/$validate?profile=eu-labraportuje, jak wynik wypada w porównaniu z profilem raportu laboratoryjnego HL7 Europe.- Do 500 wierszy na żądanie; limity są wymienione w Limity i limity szybkości.
Często zadawane pytania
Jakie formaty raportów laboratoryjnych można zaimportować do FHIR?
CSV z wierszem nagłówka (akceptowane przecinek, średnik lub tabulator, przecinek dziesiętny), wiadomości HL7 v2 ORU^R01 oraz JSON. Raporty PDF można przechowywać jako dokumenty; wyodrębnione z nich wartości wskazują z powrotem na dokument.
Co się dzieje ze znacznikami bez kodu LOINC?
Są one przechowywane pod własnym kodem laboratorium z dokładnym tekstem z raportu i wymienione w unmapped. Dodaj kolumnę LOINC dla tego laboratorium, a zostaną one zmapowane. Kod w raporcie zawsze ma pierwszeństwo przed nazwą.
Czy bezpieczne jest ponowne wysłanie raportu?
Tak. Każdy wiersz ma stabilny identyfikator zbudowany z raportu, kodu, daty i wartości, dzięki czemu zaimportowane już wiersze są pomijane; zmienione wiersze są importowane jako nowe wyniki.
Czy laboratorium może importować wyniki dla dowolnego pacjenta?
Nie. Laboratorium importuje do pacjentów, których projekt zostało utworzone lub których rekordy dana osoba udostępniła mu za pośrednictwem OAuth. Inni pacjenci dla niego nie istnieją (404).
Powiązane
- API wyników laboratoryjnych: HL7 v2 i FHIR obok siebie oraz co musi zawierać pojedynczy wynik
- Łącznik laboratoryjny: każda nazwa kolumny, pole HL7 i pole odpowiedzi
- Interoperacyjność danych medycznych: dlaczego kody i pochodzenie danych sprawiają, że wymieniane dane są użyteczne
- Integracje medyczne: przychodnie, laboratoria, urządzenia i aplikacje stron trzecich
- API danych medycznych: pisanie pojedynczych obserwacji, schorzeń i leków
- Jak zbudować aplikację AI w służbie zdrowia z backendem FHIR: wykorzystanie tych wyników w odpowiedzi AI
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card