Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card
FHIRレコードへの検査結果インポート方法
チュートリアル:CSVおよびHL7 v2 ORU^R01形式の検査レポートをLOINCコードと基準範囲を持つFHIR R4 Observationにインポートし、マッピングされていないマーカーや再送信されたレポートを処理し、各結果を検査機関に追跡する方法を説明します。
このチュートリアルでは、CSV ファイルおよび HL7 v2 ORU^R01 メッセージとしての検査レポートを、それぞれ 1 回のリクエストで患者の HL7 FHIR R4 レコードにインポートし、その結果として得られるものを示します。すなわち、LOINC コード、参照範囲、および来歴を持つ検査機関 Observation リソースです。 また、すべての検査機関統合で発生する 2 つの問題、つまり自動的にマッピングできないマーカーと二重に送信されるレポートについても説明します。すべては、合成患者を使用した無料サンドボックスで実行されます。
なぜ検査結果の保存が難しいのか
検査レポートは、マーカー、値、単位、基準範囲、日付といったシンプルなものに見えます。しかし実際には、各検査機関はマーカーに独自の名称(「ヘモグロビンA1c」、「HbA1c」、「グリコヘモグロビン」など)を使用し、小数点にはカンマやドットを使い分け、範囲を 4,0-5,6、<5、>3.5 のように記述し、何かが失敗した際には同じレポートを再送信することもあります。自由記述テキストとして保存されたこれらの結果は、経時的に比較したり、グラフ化したり、別のアプリケーションと共有したり、AIモデルに自信を持って提供したりすることができません。
FHIR レコードは、各結果を LOINC コード、UCUM 単位、値、基準範囲、日付を持つ Observation として保存し、誰が送信したかを Provenance リソースに保持します。 ラボコネクタ がその変換を行います。
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
開始する前に
platform.anpheros.com/dashboard からサンドボックスキー (sk_test_…) を取得する必要があります (サンドボックスキーを取得)。例では curl を使用していますが、SDK でも同様の呼び出し (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')
ステップ 1: CSV レポートのインポート
これは、ルーマニアの研究所がレポートをエクスポートする方法の例です。セミコロン区切り、小数点コンマ、ルーマニア語の列名、および日付は DD.MM.YYYY の形式です。コネクタは、ルーマニア語と英語の両方の列名を認識します。
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
レスポンス (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、グルコース、TSH は、その名前から LOINC にマッピングされました。小数点コンマは数値に変換され、範囲は referenceRange になりました。1 行が unmapped で返されました。レポートの正確なテキストとともに、研究所固有のコード (urn:anpheros:lab-code) の下で、まだ保存されています。そのため、何も失われていません。
ステップ 2: マッピングされていないマーカーの処理
一部の名前は判断が必要です。「Glicemie」(血糖値)が良い例です。LOINCには、血清または血漿中のグルコース(2345-7、研究所で採取された静脈サンプル)と、全血中のグルコース(2339-0、例えば指先穿刺)のコードがそれぞれあります。検査レポートでは、単に「Glicemie」と記載されている場合は血清または血漿にマッピングされます。「capilar」、「capillary」、「sânge integral」という名前は全血にマッピングされます。
{"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"}]}
コネクタが認識しないマーカーについては、コードを検索してください。
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}
その後、コードをLOINC列に送信します。レポート内のコードは、常に名前よりも優先されます。このマッピングは、ラボごとに各自で保持し、そのラボからのすべてのレポートにこの列を追加してください。
Analiza;Rezultat;UM;Interval de referinta;Data;LOINC
Glicemie;99;mg/dL;70-100;04.10.2026;2339-0
「Marker foarte rar」のような、LOINCが全くカバーしていないマーカーは、ラボのコードの下に残すことができます。これらは患者に表示され、記録に含まれます。他のラボの結果と比較することはできません。
ステップ 3: 同じレポートを 2 回送信する
検査機関はレポートを再送信します。各行には、レポート ID、コード、日付、値から構築された安定した識別子が割り当てられるため、同じレポートを 2 回インポートしても何も作成されません。
{"created": 0, "skipped": 4, "unmapped": ["Marker foarte rar"], "warnings": [], "observations": []}
変更された行(たとえば、修正された値)は、新しい結果としてインポートされます。Idempotency-Key ヘッダーは 2 番目の保証を追加します。同じキーでのネットワーク再試行は、最初の応答をそのまま返します。
ステップ 4: HL7 v2 ORU^R01 メッセージのインポート
ほとんどの検査情報システムは HL7 v2 を使用します。メッセージはそのまま(ER7 テキスト、セグメントは CR または 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 は LN コーディングシステムとして LOINC が直接使用されます。OBX-7 は基準範囲となり、OBX-8(H、N)は解釈となります。OBR-3(R-77)はプロビナンスのレポート ID として保持されます。患者は URL の患者です。患者を特定するために PID セグメントは使用されないため、間違った PID によって結果が他の人に紐付けられることはありません。
既に解析済みの結果をお持ちですか? JSON を送信してください: {"date": "2026-10-01", "origin": "report-77", "items": [{"marker": "Ferritin", "value": 38, "unit": "ng/mL", "ref_low": 15, "ref_high": 150}]}。フェリチンは LOINC 2276-4 にマッピングされます。
ステップ 5: FHIR として結果を読む
curl "$BASE/fhir/R4/Observation?patient=$PID&code=http://loinc.org|4548-4&_sort=-date&_count=1" \
-H "Authorization: Bearer $KEY"
インポートされた HbA1c は、次のように保存されます。
{
"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": "%"}}]
}
LOINC の表示名は標準的な英語名です。code.text は検査機関独自の表現を保持するため、患者は紙のレポートに記載されていた内容を引き続き確認できます。リソースと検索の詳細については、FHIR プラットフォームガイドおよびFHIR コードシステムを参照してください。
ステップ 6: 送信者の確認
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 および source_system: labx は値とともに保持されます。AI アプリケーションが後で コンテキスト API を介してこの結果を読み取るとき、それは [import/labx] としてラベル付けされるため、モデルは検査結果と患者が入力した値を区別できます。
次のステップ
- 患者はアプリで結果を確認できます。同意したどのアプリケーションでも、そのスコープ内で結果を読み取ることができます(同意とアクセスモデル)。
- 各 Observation に対して
resource.createdWebhook がトリガーされるため、クリニックのダッシュボードや AI 要約はポーリングなしで更新できます。 POST /fhir/R4/Observation/$validate?profile=eu-labは、結果が HL7 Europe の検査レポートプロファイルにどの程度準拠しているかを報告します。- リクエストあたりの行数は最大 500 行です。制限については、制限とレート制限 を参照してください。
よくある質問
FHIR にインポートできる検査レポートの形式は何ですか?
ヘッダー行付き CSV(カンマ、セミコロン、タブ区切り、10 進数コンマも可)、HL7 v2 ORU^R01 メッセージ、および JSON です。PDF レポートはドキュメントとして保存でき、そこから抽出された値はドキュメントを参照します。
LOINC コードがないマーカーはどうなりますか?
それらは、レポートの正確なテキストとともに、その検査機関独自のコードの下に保存され、unmapped にリストされます。その検査機関のために LOINC 列を追加すると、マッピングされます。レポート内のコードは常に名前よりも優先されます。
レポートを再送信しても安全ですか?
はい。各行には、レポート、コード、日付、値から構築された安定した識別子があるため、既にインポートされた行はスキップされ、変更された行は新しい結果としてインポートされます。
検査機関は任意の患者の結果をインポートできますか?
いいえ。検査機関は、そのプロジェクトが作成した患者、またはその人物が OAuth を通じて共有したレコードを持つ患者にインポートします。他の患者は(404)、その検査機関には存在しません。
関連情報
- 検査結果API: HL7 v2 と FHIR を並べて、1つの結果に何を含めるべきか
- ラボコネクタ: すべての列名、HL7フィールド、およびレスポンスフィールド
- ヘルスケアデータ相互運用性: コードと来歴が交換されたデータを利用可能にする理由
- ヘルスケア連携: クリニック、ラボ、デバイス、サードパーティ製アプリ
- 医療データAPI: 単一の観測値、病状、投薬の記述
- FHIRバックエンドを使用したAIヘルスケアアプリの構築方法: これらの結果をAI回答で使用する
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no card