TL;DR
EHR APIはEpic、Cerner、Athenahealthのようなシステムに保存されている患者の健康記録にアクセスします。ほとんどのEHRはFHIR(Fast Healthcare Interoperability Resources)をサポートしており、認証にはSMART on FHIR拡張機能付きのOAuth 2.0が使われます。テストにはApidogを利用し、FHIRリソースの検証やサンドボックスでの事前テストを行い、本番運用前に統合が患者データを正しく処理することを確認しましょう。
はじめに
電子カルテ(EHR)は診断、投薬、検査結果、アレルギー、治療計画など患者ケアに関する全情報を含みます。病院や診療所はEpic、Cerner、AthenahealthなどのEHRプラットフォームにこのデータを保存しています。
医療アプリを構築する場合、これらのEHRと安全かつリアルタイムに連携する必要があり、CSVエクスポートだけでは不十分です。EHR連携にはAPIが必須ですが、医療APIはPHI(保護された健康情報)を扱い、HIPAA等の規制を順守する必要があります。
ほとんどのEHRベンダーはFHIRを標準APIとしてサポートしていますが、認証やデータマッピングには複雑さがあります。本記事では、ApidogによるFHIRリソースのテストやサンドボックス利用方法を含め、実践的な統合手順を解説します。
このガイドを読むことで、以下が実践できるようになります。
- FHIRリソースのタイプと構造を理解
- SMART on FHIRでの認証実装
- 患者の人口統計・臨床データの取得
- 患者リソースの作成・更新
- サンドボックス環境でのテスト
FHIRを理解する
FHIR(Fast Healthcare Interoperability Resources)は医療APIの最新標準です。
- リソース: Patient, Observation, Medicationなど医療概念ごとのデータ型
- REST API: 標準操作(CRUD)
- フォーマット: JSON・XML
ベースURL構造
https://ehr.example.com/fhir/r4/{resource-type}/{id}
例:
GET https://ehr.example.com/fhir/r4/Patient/123
FHIRバージョン
多くのEHRはFHIR R4(リリース4)を利用。一部システムはDSTU2を使いますが、本ガイドはR4準拠です。
リソースタイプ
| リソース | 目的 |
|---|---|
| Patient | 人口統計・管理データ |
| Practitioner | 医療提供者 |
| Organization | 病院、診療所 |
| Observation | 検査結果、バイタルサイン |
| MedicationRequest | 処方箋 |
| Condition | 診断・問題 |
| Encounter | 受診、入院 |
| DocumentReference | 臨床文書 |
| AllergyIntolerance | アレルギー・有害反応 |
FHIRリソースの構造
患者リソースの例
{
"resourceType": "Patient",
"id": "123",
"active": true,
"name": [
{
"use": "official",
"family": "Smith",
"given": ["John", "Michael"]
}
],
"gender": "male",
"birthDate": "1985-03-15",
"address": [
{
"use": "home",
"line": ["123 Main St"],
"city": "Boston",
"state": "MA",
"postalCode": "02101",
"country": "USA"
}
],
"telecom": [
{
"system": "phone",
"value": "555-123-4567",
"use": "home"
},
{
"system": "email",
"value": "john.smith@example.com"
}
],
"identifier": [
{
"system": "http://hospital.example.org/mrn",
"value": "MRN-123456"
}
]
}
観察リソースの例
{
"resourceType": "Observation",
"id": "obs-123",
"status": "final",
"category": [
{
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/observation-category",
"code": "vital-signs",
"display": "Vital Signs"
}
]
}
],
"code": {
"coding": [
{
"system": "http://loinc.org",
"code": "8480-6",
"display": "Systolic blood pressure"
}
]
},
"subject": {
"reference": "Patient/123"
},
"effectiveDateTime": "2026-03-24T09:30:00Z",
"valueQuantity": {
"value": 120,
"unit": "mmHg",
"system": "http://unitsofmeasure.org",
"code": "mm[Hg]"
}
}
SMART on FHIRによる認証
SMART on FHIRはOAuth 2.0に医療用途向け拡張を加えたもの。患者コンテキストやEHR固有のスコープ管理が可能です。
患者アクセス用のOAuthフロー
ステップ1: 認可URLを取得
GET https://ehr.example.com/fhir/r4/.well-known/smart-configuration
レスポンス例:
{
"authorization_endpoint": "https://ehr.example.com/oauth2/authorize",
"token_endpoint": "https://ehr.example.com/oauth2/token",
"scopes_supported": [
"patient/*.read",
"patient/*.write",
"user/*.read",
"launch/patient"
]
}
ステップ2: ユーザーを認可にリダイレクト
https://ehr.example.com/oauth2/authorize?
response_type=code&
client_id=YOUR_CLIENT_ID&
redirect_uri=https://yourapp.com/callback&
scope=patient/*.read&
state=random_state_value
ステップ3: コードをトークンに交換
curl -X POST "https://ehr.example.com/oauth2/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=https://yourapp.com/callback" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
レスポンス例:
{
"access_token": "eyJhbGciOiJSUzI1NiIs...",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "patient/*.read",
"patient": "123"
}
patientフィールドが患者IDを示します。
SMARTスコープ
| スコープ | アクセス内容 |
|---|---|
patient/*.read |
患者データ全体の読み取り |
patient/Patient.read |
人口統計データのみ読み取り |
patient/Observation.read |
観察データのみ読み取り |
user/*.read |
認証ユーザーのデータ全体読み取り |
launch/patient |
患者コンテキストでアプリを起動 |
患者データの照会
患者の人口統計データ取得
curl -X GET "https://ehr.example.com/fhir/r4/Patient/123" \
-H "Authorization: Bearer ACCESS_TOKEN"
観察データ検索
curl -X GET "https://ehr.example.com/fhir/r4/Observation?patient=123&category=vital-signs" \
-H "Authorization: Bearer ACCESS_TOKEN"
レスポンスはBundle形式:
{
"resourceType": "Bundle",
"type": "searchset",
"total": 5,
"entry": [
{
"resource": { ... Observation resource ... }
}
]
}
一般的な検索パラメータ
# 日付範囲指定
GET /Observation?patient=123&category=laboratory&date=gt2026-01-01
# LOINCコード指定
GET /Observation?patient=123&code=http://loinc.org|8480-6
# 投薬
GET /MedicationRequest?patient=123&status=active
# 診断
GET /Condition?patient=123&clinical-status=active
# 受診記録
GET /Encounter?patient=123&type=AMB
ページネーション
GET /Observation?patient=123&_count=20
レスポンス例:
{
"link": [
{
"relation": "next",
"url": "https://ehr.example.com/fhir/r4/Observation?patient=123&_count=20&page=2"
}
]
}
リソースの作成と更新
観察データの作成
curl -X POST "https://ehr.example.com/fhir/r4/Observation" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/fhir+json" \
-d '{
"resourceType": "Observation",
"status": "final",
"code": {
"coding": [{
"system": "http://loinc.org",
"code": "8480-6",
"display": "Systolic blood pressure"
}]
},
"subject": {
"reference": "Patient/123"
},
"effectiveDateTime": "2026-03-24T09:30:00Z",
"valueQuantity": {
"value": 118,
"unit": "mmHg",
"system": "http://unitsofmeasure.org",
"code": "mm[Hg]"
}
}'
患者の更新
curl -X PUT "https://ehr.example.com/fhir/r4/Patient/123" \
-H "Authorization: Bearer ACCESS_TOKEN" \
-H "Content-Type: application/fhir+json" \
-d '{
"resourceType": "Patient",
"id": "123",
"name": [{
"family": "Smith",
"given": ["John", "Michael"]
}],
"telecom": [{
"system": "phone",
"value": "555-999-8888",
"use": "home"
}]
}'
EHRベンダー固有の詳細
Epic
- ベースURL:
https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4/ - サンドボックス:
https://fhir.epic.com/test/api/FHIR/R4/ - ドキュメント: https://fhir.epic.com
Epic本番環境アクセスにはアプリ登録が必須です。
Cerner (Oracle Health)
- ベースURL:
https://fhir-myrecord.cerner.com/r4/{tenant-id} - サンドボックス:
https://fhir-deprecated.cerner.com/r4/ec2458f2-1e24-41c8-b71b-0e701af7583d - ドキュメント: https://docs.oracle.com/en/health/health-cerner/
Athenahealth
- ベースURL:
https://api.platform.athenahealth.com/fhir/r4/{practice-id} - サンドボックス: 開発者プログラム経由で提供
- ドキュメント: https://docs.athenahealth.com
Apidogでのテスト
医療APIではテストが極めて重要です。患者データは機密性が高いため、サンドボックスやリソース検証を徹底しましょう。
1. 公開サンドボックス利用
下記の公開FHIRサンドボックスでテストを行います。
# HAPI FHIR(オープンソース)
https://hapi.fhir.org/baseR4
# SMART Health ITサンドボックス
https://launch.smarthealthit.org
2. FHIRリソース検証例 (Apidog テストスクリプト)
pm.test('Resource is valid Patient', () => {
const response = pm.response.json()
pm.expect(response.resourceType).to.eql('Patient')
pm.expect(response.id).to.exist
pm.expect(response.name).to.be.an('array')
})
pm.test('Observation has required fields', () => {
const resource = pm.response.json()
pm.expect(resource.status).to.exist
pm.expect(resource.code).to.exist
pm.expect(resource.subject).to.exist
})
3. 認証フローのテスト
SMART構成情報を環境変数として設定します。
AUTHORIZATION_ENDPOINT: https://ehr.example.com/oauth2/authorize
TOKEN_ENDPOINT: https://ehr.example.com/oauth2/token
CLIENT_ID: your_client_id
CLIENT_SECRET: your_client_secret
SCOPE: patient/*.read
コンプライアンスに関する考慮事項
HIPAA
米国で医療アプリを運用する場合、以下の点に配慮しましょう。
- データ伝送: TLS 1.2以上を必須
- データ保存: 保存時の暗号化
- アクセス制御: 監査ログと最小権限
- BAA契約: EHRベンダーとビジネスアソシエイト契約を締結
SMART on FHIRのセキュリティ
- アクセストークンは有効期限あり(通常1時間)
- 長期セッションにはリフレッシュトークンを利用
- 患者コンテキストはトークンスコープに紐づく
- ログアウト時はトークンの失効が必要
データ最小化
必要なスコープのみ取得しましょう。
- 良い例:
patient/Observation.read - 避けるべき:
patient/*.read(不要な場合)
一般的なエラーと修正
401 認証エラー
- 原因: トークン期限切れ/無効
- 対策: リフレッシュトークンで更新
403 アクセス禁止
- 原因: スコープ不足
- 対策: 必要スコープを確認し認可リクエスト時に追加
404 リソース未検出
- 原因: 患者やリソースが存在しない
- 対策: ID・患者コンテキストを再確認
422 バリデーションエラー
- 原因: FHIRリソース検証失敗
- 対策: 必須フィールド・用語の不足を修正
例:
{
"resourceType": "OperationOutcome",
"issue": [{
"severity": "error",
"code": "required",
"details": {
"text": "Observation.status is required"
}
}]
}
代替案と比較
| 機能 | Epic | Cerner | Athenahealth | OpenEMR |
|---|---|---|---|---|
| FHIR R4 | ✓ | ✓ | ✓ | 部分的 |
| SMART on FHIR | ✓ | ✓ | ✓ | いいえ |
| サンドボックス | ✓ | ✓ | 制限あり | 自己ホスト |
| APIドキュメント | 素晴らしい | 良い | 良い | 基本的 |
| 市場シェア | 大規模病院 | 医療システム | 小規模診療所 | オープンソース |
Epic・Cernerは大規模医療機関向け、Athenahealthは小規模診療所向け、OpenEMRはOSSですがAPIサポートは限定的です。
実世界のユースケース
- 患者ポータル: Epicから患者データを取得し、検査結果や予約情報を表示するポータル。SMART on FHIR認証+FHIR API利用。
- 臨床研究: 製薬会社が複数病院のFHIR APIを照会し、基準に合致する患者を同意管理下で抽出。
- リモートモニタリング: 遠隔医療会社が患者のバイタルサインをFHIR ObservationでEHRへ記録し、臨床医へ即時共有。
まとめ
本記事の要点:
- FHIRは医療APIの標準
- 各リソースは患者・観察など医療概念を表現
- SMART on FHIRでOAuth認証を実装
- EHRごとの固有事項に注意
- サンドボックスで十分なテストを
次のステップ:
- HAPI FHIR公開サンドボックスを試す
- 必要なFHIRリソースタイプを特定
- EHR開発者プログラムに登録
- モック患者データでApidogテスト
- HIPAA対応のデータ処理を実装
ApidogでFHIR APIをテスト - 無料
FAQ
FHIRとHL7 v2の違いは?
HL7 v2は古いメッセージング標準(病院間インターフェース用)、FHIRはREST APIベースの新標準です。新規統合はFHIRが主流、レガシーではHL7 v2も利用されます。
EHR APIにBAA契約は必要?
PHIを扱う場合は必須です。ビジネスアソシエイト契約(BAA)はEHR業者と締結が必要です。必ずEHRベンダーのコンプライアンス部門に相談しましょう。
EpicのFHIR APIにアクセスするには?
Epic App Orchardマーケットプレイスで登録。テストには公開サンドボックス、本番アクセスには病院の承認が必要です。
患者コンテキストとは?
SMART on FHIRトークンに患者IDが含まれることで、API呼び出しがその患者のデータに限定されます。
EHRにデータを書き込める?
観察データ作成や人口統計更新は可。診断や投薬の書き込みは通常、追加の臨床承認が必要です。
用語コードはどう扱う?
FHIRリソース作成時は標準用語を使用:
- 検査・観察: LOINC
- 臨床概念: SNOMED CT
- 診断: ICD-10
- 投薬: RxNorm
国際的な医療利用は?
FHIRはグローバル規格。各国ごとに実装ガイドがあり、米国はUS Coreプロファイルを利用します。自国仕様を確認してください。

Top comments (0)