Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
Comment importer des résultats de laboratoire dans un dossier FHIR
Tutoriel : importer un rapport de laboratoire en CSV et en HL7 v2 ORU^R01 dans des Observations FHIR R4 avec des codes LOINC et des plages de référence, gérer les marqueurs non mappés et les rapports renvoyés, et tracer chaque résultat vers son laboratoire.
Ce tutoriel prend un rapport de laboratoire sous forme de fichier CSV et de message HL7 v2 ORU^R01, l'importe dans le dossier HL7 FHIR R4 d'un patient en une seule requête chacun, et montre ce que vous obtenez en retour : des ressources de laboratoire Observation avec des codes LOINC, des plages de référence et la provenance. Il couvre également les deux problèmes que toute intégration de laboratoire rencontre : les marqueurs qui ne peuvent pas être mappés automatiquement et les rapports qui sont envoyés deux fois. Tout fonctionne sur le bac à sable gratuit avec un patient synthétique.
Pourquoi les résultats de laboratoire sont difficiles à stocker
Un rapport de laboratoire semble simple : un marqueur, une valeur, une unité, une plage de référence, une date. En pratique, chaque laboratoire nomme les marqueurs à sa manière ("Hemoglobina glicozilata", "HbA1c", "Glycated haemoglobin"), utilise des virgules ou des points pour les décimales, écrit les plages comme 4,0-5,6, <5 ou >3.5, et renvoie le même rapport en cas d'échec. Stockés sous forme de texte libre, ces résultats ne peuvent pas être comparés dans le temps, tracés, partagés avec une autre application ou donnés à un modèle d'IA avec confiance.
Un enregistrement FHIR stocke chaque résultat comme un Observation avec un code LOINC, une unité UCUM, une valeur, une plage de référence et une date, et conserve qui l'a envoyé dans une ressource Provenance. Le connecteur de laboratoire effectue cette conversion pour vous.
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
Avant de commencer
Vous avez besoin d'une clé sandbox (sk_test_…) depuis platform.anpheros.com/dashboard (Obtenir une clé sandbox). Les exemples utilisent curl ; les SDK ont les mêmes appels (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')
Étape 1 : importer un rapport CSV
Voici comment un laboratoire roumain pourrait exporter un rapport : points-virgules, virgules décimales, noms de colonnes roumains et dates comme DD.MM.YYYY. Le connecteur reconnaît les noms de colonnes roumains et anglais.
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
La réponse (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, glucose et TSH ont été mappés à LOINC à partir de leurs noms. Les virgules décimales sont devenues des nombres, et les plages sont devenues referenceRange. Une ligne est revenue dans unmapped. Elle est toujours stockée, sous le code propre au laboratoire (urn:anpheros:lab-code) avec le texte exact du rapport, de sorte que rien n'est perdu.
Étape 2 : gérer les marqueurs non mappés
Certains noms nécessitent une décision. "Glicemie" (glycémie) en est un bon exemple : LOINC a un code pour le glucose dans le sérum ou le plasma (2345-7, un échantillon veineux prélevé en laboratoire) et un autre pour le glucose dans le sang total (2339-0, par exemple une piqûre au doigt). Sur un rapport de laboratoire, un simple "Glicemie" est mappé au sérum ou au plasma. Un nom indiquant "capilar", "capillary" ou "sânge integral" est mappé au sang total :
{"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"}]}
Pour les marqueurs que le connecteur ne reconnaît pas, recherchez le code :
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}
Envoyez ensuite le code dans une colonne LOINC. Un code dans le rapport l'emporte toujours sur le nom. Conservez ce mappage par laboratoire de votre côté et ajoutez la colonne à chaque rapport provenant de celui-ci :
Analiza;Rezultat;UM;Interval de referinta;Data;LOINC
Glicemie;99;mg/dL;70-100;04.10.2026;2339-0
Les marqueurs que LOINC ne couvre pas du tout, comme le "Marker foarte rar" inventé, peuvent rester sous le code du laboratoire. Ils sont présentés au patient et inclus dans le dossier. Ils ne peuvent pas être comparés aux résultats d'autres laboratoires.
Étape 3 : envoyer le même rapport deux fois
Les laboratoires renvoient les rapports. Chaque ligne obtient un identifiant stable construit à partir de l'ID du rapport, du code, de la date et de la valeur, de sorte qu'une deuxième importation du même rapport ne crée rien :
{"created": 0, "skipped": 4, "unmapped": ["Marker foarte rar"], "warnings": [], "observations": []}
Les lignes qui ont changé, une valeur corrigée par exemple, sont importées comme de nouveaux résultats. L'en-tête Idempotency-Key ajoute une deuxième garantie : une nouvelle tentative réseau avec la même clé renvoie la première réponse inchangée.
Étape 4 : Importer un message HL7 v2 ORU^R01
La plupart des systèmes d'information de laboratoire utilisent HL7 v2. Envoyez le message tel quel (texte ER7, segments séparés par CR ou 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 avec le système de codage LN est utilisé directement comme LOINC. OBX-7 devient la plage de référence et OBX-8 (H, N) l'interprétation. OBR-3 (R-77) est conservé comme identifiant de rapport dans la provenance. Le patient est celui de l'URL : le segment PID n'est pas utilisé pour trouver un patient, donc un PID incorrect ne peut pas attacher de résultats à quelqu'un d'autre.
Vous avez déjà des résultats analysés ? Envoyez du JSON : {"date": "2026-10-01", "origin": "report-77", "items": [{"marker": "Ferritin", "value": 38, "unit": "ng/mL", "ref_low": 15, "ref_high": 150}]}. La ferritine est mappée au LOINC 2276-4.
Étape 5 : lire les résultats en tant que FHIR
curl "$BASE/fhir/R4/Observation?patient=$PID&code=http://loinc.org|4548-4&_sort=-date&_count=1" \
-H "Authorization: Bearer $KEY"
L'HbA1c importé, tel qu'il est stocké :
{
"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": "%"}}]
}
Le nom d'affichage LOINC est le nom standard en anglais. code.text conserve la formulation propre au laboratoire, de sorte que le patient voit toujours ce qui figurait sur le rapport papier. Pour en savoir plus sur les ressources et la recherche, consultez le guide de la plateforme FHIR et les systèmes de codes FHIR.
Étape 6 : vérifier qui l'a envoyé
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 et source_system: labx restent avec la valeur. Lorsqu'une application d'IA lit plus tard ce résultat via l'API de contexte, il est étiqueté [import/labx], permettant ainsi au modèle de distinguer un résultat de laboratoire d'une valeur saisie par le patient.
Et ensuite ?
- Le patient consulte les résultats dans son application. Toute application à laquelle il a consenti peut les lire, dans le cadre de ses scopes (modèle de consentement et d'accès).
- Un webhook
resource.createdest déclenché pour chaque Observation, permettant à un tableau de bord de clinique ou à un résumé IA de se mettre à jour sans interroger. POST /fhir/R4/Observation/$validate?profile=eu-labindique comment un résultat se compare au profil de rapport de laboratoire HL7 Europe.- Jusqu'à 500 lignes par requête ; les limites sont listées dans Limites et limitations de débit.
Foire aux questions
Quels formats de rapports de laboratoire peuvent être importés dans FHIR ?
CSV avec une ligne d'en-tête (virgule, point-virgule ou tabulation, virgule décimale acceptée), messages HL7 v2 ORU^R01 et JSON. Les rapports PDF peuvent être stockés comme documents ; les valeurs extraites d'eux renvoient au document.
Que deviennent les marqueurs sans code LOINC ?
Ils sont stockés sous le code propre au laboratoire avec le texte exact du rapport et listés dans unmapped. Ajoutez une colonne LOINC pour ce laboratoire et ils seront mappés. Un code dans le rapport a toujours la priorité sur le nom.
Est-il sûr de renvoyer un rapport ?
Oui. Chaque ligne possède un identifiant stable construit à partir du rapport, du code, de la date et de la valeur, de sorte que les lignes déjà importées sont ignorées ; les lignes modifiées sont importées comme de nouveaux résultats.
Un laboratoire peut-il importer des résultats pour n'importe quel patient ?
Non. Un laboratoire importe dans les patients son projet créé ou dont les enregistrements ont été partagés avec lui via OAuth. Les autres patients n'existent pas pour lui (404).
Liens connexes
- API des résultats de laboratoire : HL7 v2 et FHIR côte à côte, et ce qu'un résultat doit contenir
- Connecteur de laboratoire : chaque nom de colonne, champ HL7 et champ de réponse
- Interopérabilité des données de santé : pourquoi les codes et la provenance rendent les données échangées utilisables
- Intégrations de santé : cliniques, laboratoires, appareils et applications tierces
- API de données médicales : écriture d'observations uniques, de conditions et de médicaments
- Comment créer une application de santé IA avec un backend FHIR : utilisation de ces résultats dans une réponse IA
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card