HL7 FHIR API の使い方:完全医療連携ガイド (2026年)

Ashley Innocent

Ashley Innocent

25 3月 2026

HL7 FHIR API の使い方:完全医療連携ガイド (2026年)

TL;DR

HL7 FHIR(Fast Healthcare Interoperability Resources)は、RESTful APIとJSON/XMLレスポンスを使用する、医療データ交換のための最新標準です。患者、観察結果、薬剤などに関する標準化されたリソースを提供し、OAuth 2.0認証とアプリ統合のためのSMART on FHIRを備えています。このガイドでは、FHIRのアーキテクチャ、リソースタイプ、検索パラメーター、認証、および本番環境での実装戦略について説明します。

はじめに

医療データの断片化により、米国の医療システムは年間300億ドルのコストを負担しています。医療アプリケーションを構築する開発者にとって、HL7 FHIR APIの統合は選択肢ではなく、CMSによって義務付けられ、Epic、Cerner、およびすべての主要な電子カルテ(EHR)ベンダーに採用されている業界標準です。

現実を見てみましょう。FHIR対応アプリを使用する医療提供者は、ケア連携時間を40%短縮し、FAXベースの記録要求を85%削減しています。堅牢なFHIR API統合により、EHR、患者ポータル、ケア連携プラットフォーム間でシームレスなデータ交換が可能になります。

このガイドでは、HL7 FHIR APIの統合プロセス全体を説明します。FHIRのアーキテクチャ、リソースタイプ、検索パラメーター、OAuth 2.0認証、SMART on FHIR統合、および本番デプロイ戦略を学びます。最終的には、本番環境に対応したFHIR統合が完了するでしょう。

💡
Apidogは、医療API統合を簡素化します。FHIRエンドポイントのテスト、リソーススキーマの検証、認証フローのデバッグ、API仕様のドキュメント化をすべて1つのワークスペースで行えます。FHIR実装ガイドのインポート、モックレスポンスの作成、テストシナリオのチームとの共有も可能です。
button

HL7 FHIRとは?

FHIR (Fast Healthcare Interoperability Resources) は、医療情報を電子的に交換するための標準フレームワークです。Health Level Seven International (HL7) によって開発されたFHIRは、RESTful API、JSON、XML、OAuth 2.0などの最新のウェブ技術を使用しています。

FHIRリソースタイプ

FHIRは140以上のリソースタイプを定義しています。コアリソースは以下の通りです。

リソース 目的 一般的なユースケース
Patient デモグラフィック情報 患者検索、登録
Practitioner 医療従事者情報 ディレクトリ、スケジューリング
Encounter 受診/入院 ケアエピソード、請求
Observation 臨床データ バイタル、検査結果、評価
Condition 問題/診断 問題リスト、ケアプランニング
MedicationRequest 処方箋 e-処方、薬剤履歴
AllergyIntolerance アレルギー 安全確認、アラート
Immunization 予防接種 予防接種記録
DiagnosticReport 検査/画像診断レポート 結果配信
DocumentReference 臨床文書 CCD、退院サマリー

FHIR APIアーキテクチャ

FHIRはRESTful API構造を使用します。

https://fhir-server.com/fhir/{resourceType}/{id}

FHIRバージョン比較

バージョン ステータス ユースケース
R4 (4.0.1) 現在のSTU 本番環境での実装
R4B (4.3) 試用実装 早期導入者
R5 (5.0.0) ドラフトSTU 将来の実装
DSTU2 非推奨 レガシーシステムのみ

CMSは、認定EHRに対し、患者アクセスおよび医療提供者アクセスAPIでFHIR R4をサポートすることを要求しています。

開始する:FHIRサーバーへのアクセス

ステップ1:FHIRサーバーの選択

FHIRサーバーデプロイのオプション:

サーバー タイプ コスト 最適な用途
Azure API for FHIR マネージド 従量課金制 エンタープライズ、Azureユーザー
AWS HealthLake マネージド 従量課金制 AWS環境
Google Cloud Healthcare API マネージド 従量課金制 GCP環境
HAPI FHIR オープンソース セルフホスト カスタムデプロイ
Epic FHIR Server 商用 Epic顧客 Epic EHRとの統合
Cerner Ignite FHIR 商用 Cerner顧客 Cerner EHRとの統合

ステップ2:サーバー認証情報の取得

クラウドFHIRサービスの場合:

# Azure API for FHIR
# 1. Azure PortalでFHIRサービスを作成
# 2. 認証を構成 (OAuth 2.0 または AAD)
# 3. FHIRエンドポイントを取得: https://{service-name}.azurehealthcareapis.com
# 4. OAuth用のクライアントアプリを登録

# AWS HealthLake
# 1. AWSコンソールでデータストアを作成
# 2. IAMロールを構成
# 3. エンドポイントを取得: https://healthlake.{region}.amazonaws.com

ステップ3:FHIR RESTful操作の理解

FHIRは標準的なHTTPメソッドをサポートしています。

操作 HTTPメソッド エンドポイント 説明
Read GET /{resourceType}/{id} 特定のリソースを取得
Search GET /{resourceType}?param=value リソースを検索
Create POST /{resourceType} 新しいリソースを作成
Update PUT /{resourceType}/{id} リソースを置き換え
Patch PATCH /{resourceType}/{id} 部分的な更新
Delete DELETE /{resourceType}/{id} リソースを削除
History GET /{resourceType}/{id}/_history リソースのバージョン履歴

ステップ4:最初のFHIR呼び出しを行う

接続をテストします。

curl -X GET "https://fhir-server.com/fhir/metadata" \
  -H "Accept: application/fhir+json" \
  -H "Authorization: Bearer {token}"

期待されるレスポンス:

{
  "resourceType": "CapabilityStatement",
  "status": "active",
  "date": "2026-03-25",
  "fhirVersion": "4.0.1",
  "rest": [{
    "mode": "server",
    "resource": [
      { "type": "Patient" },
      { "type": "Observation" },
      { "type": "Condition" }
    ]
  }]
}

コアFHIR操作

患者リソースの読み取り

IDで患者をフェッチします。

const FHIR_BASE_URL = process.env.FHIR_BASE_URL;
const FHIR_TOKEN = process.env.FHIR_TOKEN;

const fhirRequest = async (endpoint, options = {}) => {
  const response = await fetch(`${FHIR_BASE_URL}/fhir${endpoint}`, {
    ...options,
    headers: {
      'Accept': 'application/fhir+json',
      'Authorization': `Bearer ${FHIR_TOKEN}`,
      ...options.headers
    }
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`FHIR Error: ${error.issue?.[0]?.details?.text || response.statusText}`);
  }

  return response.json();
};

// IDで患者を読み込む
const getPatient = async (patientId) => {
  const patient = await fhirRequest(`/Patient/${patientId}`);
  return patient;
};

// 使用例
const patient = await getPatient('12345');
console.log(`Patient: ${patient.name[0].given[0]} ${patient.name[0].family}`);
console.log(`DOB: ${patient.birthDate}`);
console.log(`Gender: ${patient.gender}`);

患者リソースの構造

{
  "resourceType": "Patient",
  "id": "12345",
  "identifier": [
    {
      "use": "usual",
      "type": {
        "coding": [{
          "system": "http://terminology.hl7.org/CodeSystem/v2-0203",
          "code": "MR"
        }]
      },
      "system": "http://hospital.example.org",
      "value": "MRN123456"
    }
  ],
  "name": [
    {
      "use": "official",
      "family": "Smith",
      "given": ["John", "Michael"]
    }
  ],
  "telecom": [
    {
      "system": "phone",
      "value": "555-123-4567",
      "use": "home"
    },
    {
      "system": "email",
      "value": "john.smith@email.com"
    }
  ],
  "gender": "male",
  "birthDate": "1985-06-15",
  "address": [
    {
      "use": "home",
      "line": ["123 Main Street"],
      "city": "Springfield",
      "state": "IL",
      "postalCode": "62701"
    }
  ]
}

リソースの検索

名前で患者を検索します。

const searchPatients = async (searchParams) => {
  const query = new URLSearchParams();

  // 検索パラメーターを追加
  if (searchParams.name) {
    query.append('name', searchParams.name);
  }
  if (searchParams.birthDate) {
    query.append('birthdate', searchParams.birthDate);
  }
  if (searchParams.identifier) {
    query.append('identifier', searchParams.identifier);
  }
  if (searchParams.gender) {
    query.append('gender', searchParams.gender);
  }

  const response = await fhirRequest(`/Patient?${query.toString()}`);
  return response;
};

// 使用例
const results = await searchPatients({ name: 'Smith', birthDate: '1985-06-15' });

console.log(`Found ${results.total} patients`);
results.entry.forEach(entry => {
  const patient = entry.resource;
  console.log(`${patient.name[0].family}, ${patient.name[0].given[0]}`);
});

共通の検索パラメーター

リソース 検索パラメーター
Patient name, birthdate, identifier, gender, phone, email ?name=Smith&birthdate=1985-06-15
Observation patient, code, date, category, status ?patient=123&code=8480-6&date=ge2026-01-01
Condition patient, clinical-status, category, onset-date ?patient=123&clinical-status=active
MedicationRequest patient, status, intent, medication ?patient=123&status=active
Encounter patient, date, status, class ?patient=123&date=ge2026-01-01
DiagnosticReport patient, category, date, status ?patient=123&category=laboratory

検索修飾子

修飾子 説明
:exact 完全一致 name:exact=Smith
:contains 部分一致 name:contains=smi
:missing 値の有無 phone:missing=true
: (プレフィックス) プレフィックス演算子 birthdate=ge1980-01-01

日付と数値の検索プレフィックス

プレフィックス 意味
eq 等しい birthdate=eq1985-06-15
ne 等しくない birthdate=ne1985-06-15
gt より大きい birthdate=gt1980-01-01
lt より小さい birthdate=lt1990-01-01
ge 以上 birthdate=ge1980-01-01
le 以下 birthdate=le1990-01-01
sa より後 date=sa2026-01-01
eb より前 date=eb2026-12-31

臨床データの操作

Observation(バイタルサイン)の作成

バイタルサインを記録します。

const createObservation = async (observationData) => {
  const observation = {
    resourceType: 'Observation',
    status: 'final',
    category: [
      {
        coding: [{
          system: 'http://terminology.hl7.org/CodeSystem/observation-category',
          code: 'vital-signs'
        }]
      }
    ],
    code: {
      coding: [{
        system: 'http://loinc.org',
        code: observationData.code, // 例: 収縮期血圧の場合は '8480-6'
        display: observationData.display
      }]
    },
    subject: {
      reference: `Patient/${observationData.patientId}`
    },
    effectiveDateTime: observationData.effectiveDate || new Date().toISOString(),
    valueQuantity: {
      value: observationData.value,
      unit: observationData.unit,
      system: 'http://unitsofmeasure.org',
      code: observationData.ucumCode
    },
    performer: [
      {
        reference: `Practitioner/${observationData.performerId}`
      }
    ]
  };

  const response = await fhirRequest('/Observation', {
    method: 'POST',
    body: JSON.stringify(observation)
  });

  return response;
};

// 使用例 - 血圧の記録
const systolicBP = await createObservation({
  patientId: '12345',
  code: '8480-6',
  display: 'Systolic blood pressure',
  value: 120,
  unit: 'mmHg',
  ucumCode: 'mm[Hg]',
  performerId: '67890'
});

console.log(`Observation created: ${systolicBP.id}`);

一般的なLOINCコード

コード 表示 カテゴリ
8480-6 収縮期血圧 バイタルサイン
8462-4 拡張期血圧 バイタルサイン
8867-4 心拍数 バイタルサイン
8310-5 体温 バイタルサイン
8302-2 身長 バイタルサイン
29463-7 体重 バイタルサイン
8871-5 呼吸数 バイタルサイン
2339-0 血糖 [質量/容積] 検査
4548-4 ヘモグロビンA1c 検査
2093-3 コレステロール [質量/容積] 検査

Condition(問題リスト項目)の作成

問題リストに診断を追加します。

const createCondition = async (conditionData) => {
  const condition = {
    resourceType: 'Condition',
    clinicalStatus: {
      coding: [{
        system: 'http://terminology.hl7.org/CodeSystem/condition-clinical',
        code: conditionData.status || 'active'
      }]
    },
    verificationStatus: {
      coding: [{
        system: 'http://terminology.hl7.org/CodeSystem/condition-ver-status',
        code: 'confirmed'
      }]
    },
    category: [
      {
        coding: [{
          system: 'http://terminology.hl7.org/CodeSystem/condition-category',
          code: conditionData.category || 'problem-list-item'
        }]
      }
    ],
    code: {
      coding: [{
        system: 'http://snomed.info/sct',
        code: conditionData.sctCode,
        display: conditionData.display
      }]
    },
    subject: {
      reference: `Patient/${conditionData.patientId}`
    },
    onsetDateTime: conditionData.onsetDate,
    recordedDate: new Date().toISOString()
  };

  const response = await fhirRequest('/Condition', {
    method: 'POST',
    body: JSON.stringify(condition)
  });

  return response;
};

// 使用例 - 問題リストに糖尿病を追加
const diabetes = await createCondition({
  patientId: '12345',
  sctCode: '44054006',
  display: 'Type 2 Diabetes Mellitus',
  status: 'active',
  category: 'problem-list-item',
  onsetDate: '2024-01-15'
});

一般的なSNOMED CTコード

コード 表示 カテゴリ
44054006 2型糖尿病 問題
38341003 高血圧 問題
195967001 喘息 問題
13645005 慢性閉塞性肺疾患 問題
35489007 うつ病性障害 問題
22298006 心筋梗塞 問題
26929004 アルツハイマー病 問題
396275006 変形性関節症 問題

患者の薬剤情報の取得

アクティブな薬剤依頼を取得します。

const getPatientMedications = async (patientId) => {
  const response = await fhirRequest(
    `/MedicationRequest?patient=${patientId}&status=active`
  );

  return response;
};

// 使用例
const medications = await getPatientMedications('12345');

medications.entry?.forEach(entry => {
  const med = entry.resource;
  console.log(`${med.medicationCodeableConcept.coding[0].display}`);
  console.log(`  Dose: ${med.dosageInstruction[0]?.text}`);
  console.log(`  Status: ${med.status}`);
});

検査結果の取得

診断レポートと観察結果を取得します。

const getPatientLabResults = async (patientId, options = {}) => {
  const params = new URLSearchParams({
    patient: patientId,
    category: options.category || 'laboratory'
  });

  if (options.dateFrom) {
    params.append('date', `ge${options.dateFrom}`);
  }

  const response = await fhirRequest(`/DiagnosticReport?${params.toString()}`);
  return response;
};

// 特定の検査値(例: HbA1c)を取得
const getLabValue = async (patientId, loincCode) => {
  const params = new URLSearchParams({
    patient: patientId,
    code: loincCode
  });

  const response = await fhirRequest(`/Observation?${params.toString()}`);
  return response;
};

// 使用例 - HbA1cの結果を取得
const hba1c = await getLabValue('12345', '4548-4');
hba1c.entry?.forEach(entry => {
  const obs = entry.resource;
  console.log(`HbA1c: ${obs.valueQuantity.value} ${obs.valueQuantity.unit}`);
  console.log(`Date: ${obs.effectiveDateTime}`);
});

OAuth 2.0とSMART on FHIR

FHIR認証の理解

FHIRサーバーはOpenID Connect付きのOAuth 2.0を使用します。

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   クライアント    │───▶│   認証        │───▶│   FHIR        │
│   (アプリ)    │    │   サーバー    │    │   サーバー    │
└─────────────┘    └─────────────┘    └─────────────┘
     │                    │                    │
     │  1. 認証リクエスト  │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │  2. ユーザーログイン │                    │
     │◀───────────────────│                    │
     │                    │                    │
     │  3. 認証コード     │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │  4. トークンリクエスト │                    │
     │───────────────────▶│                    │
     │                    │  5. トークン + ID │
     │◀───────────────────│                    │
     │                    │                    │
     │  6. APIリクエスト  │                    │
     │────────────────────────────────────────▶│
     │                    │                    │
     │  7. FHIRデータ     │                    │
     │◀────────────────────────────────────────│

SMART on FHIRアプリの起動

SMARTアプリの起動を実装します。

const crypto = require('crypto');

class SMARTClient {
  constructor(config) {
    this.clientId = config.clientId;
    this.redirectUri = config.redirectUri;
    this.issuer = config.issuer; // FHIRサーバーのURL
    this.scopes = config.scopes;
  }

  generatePKCE() {
    const codeVerifier = crypto.randomBytes(32).toString('base64url');
    const codeChallenge = crypto
      .createHash('sha256')
      .update(codeVerifier)
      .digest('base64url');

    return { codeVerifier, codeChallenge };
  }

  buildAuthUrl(state, patientId = null) {
    const { codeVerifier, codeChallenge } = this.generatePKCE();

    // トークン交換のためにcodeVerifierを保存
    this.codeVerifier = codeVerifier;

    const params = new URLSearchParams({
      response_type: 'code',
      client_id: this.clientId,
      redirect_uri: this.redirectUri,
      scope: this.scopes.join(' '),
      state: state,
      code_challenge: codeChallenge,
      code_challenge_method: 'S256',
      aud: this.issuer,
      launch: patientId ? `patient-${patientId}` : null
    });

    return `${this.issuer}/authorize?${params.toString()}`;
  }

  async exchangeCodeForToken(code) {
    const response = await fetch(`${this.issuer}/token`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded'
      },
      body: new URLSearchParams({
        grant_type: 'authorization_code',
        code: code,
        redirect_uri: this.redirectUri,
        client_id: this.clientId,
        code_verifier: this.codeVerifier
      })
    });

    const data = await response.json();

    return {
      accessToken: data.access_token,
      refreshToken: data.refresh_token,
      expiresIn: data.expires_in,
      patientId: data.patient,
      encounterId: data.encounter
    };
  }
}

// 使用例
const smartClient = new SMARTClient({
  clientId: 'my-app-client-id',
  redirectUri: 'https://myapp.com/callback',
  issuer: 'https://fhir.epic.com',
  scopes: [
    'openid',
    'profile',
    'patient/Patient.read',
    'patient/Observation.read',
    'patient/Condition.read',
    'patient/MedicationRequest.read',
    'offline_access'
  ]
});

// ユーザーを認証URLにリダイレクト
const state = crypto.randomBytes(16).toString('hex');
const authUrl = smartClient.buildAuthUrl(state);
console.log(`Redirect to: ${authUrl}`);

必須SMARTスコープ

スコープ パーミッション ユースケース
openid OIDC認証 すべてのアプリに必須
profile ユーザープロファイル情報 医療従事者ディレクトリ
patient/Patient.read 患者デモグラフィック情報の読み取り 患者検索
patient/Observation.read 観察結果の読み取り バイタル、検査
patient/Condition.read 状態の読み取り 問題リスト
patient/MedicationRequest.read 薬剤情報の読み取り 薬剤履歴
patient/*.read すべての患者リソースの読み取り 患者データの全体像
user/*.read アクセス可能なすべてのリソースの読み取り 医療従事者ビュー
offline_access リフレッシュトークン 長時間セッション

認証済みFHIRリクエストの作成

class FHIRClient {
  constructor(accessToken, fhirBaseUrl) {
    this.accessToken = accessToken;
    this.baseUrl = fhirBaseUrl;
  }

  async request(endpoint, options = {}) {
    const response = await fetch(`${this.baseUrl}/fhir${endpoint}`, {
      ...options,
      headers: {
        'Accept': 'application/fhir+json',
        'Authorization': `Bearer ${this.accessToken}`,
        ...options.headers
      }
    });

    if (!response.ok) {
      const error = await response.json();
      throw new Error(`FHIR Error: ${error.issue?.[0]?.details?.text}`);
    }

    return response.json();
  }

  async getPatient(patientId) {
    return this.request(`/Patient/${patientId}`);
  }

  async searchPatients(params) {
    const query = new URLSearchParams(params);
    return this.request(`/Patient?${query.toString()}`);
  }
}

// OAuthコールバック後の使用例
const fhirClient = new FHIRClient(tokens.accessToken, 'https://fhir.epic.com');
const patient = await fhirClient.getPatient(tokens.patientId);

バッチおよびトランザクション操作

バッチリクエスト

複数の独立したリクエストを実行します。

const batchRequest = async (requests) => {
  const bundle = {
    resourceType: 'Bundle',
    type: 'batch',
    entry: requests.map(req => ({
      resource: req.resource,
      request: {
        method: req.method,
        url: req.url
      }
    }))
  };

  const response = await fhirRequest('', {
    method: 'POST',
    body: JSON.stringify(bundle)
  });

  return response;
};

// 使用例 - 複数のリソースをフェッチ
const bundle = await batchRequest([
  { method: 'GET', url: 'Patient/12345' },
  { method: 'GET', url: 'Patient/12345/Observation?category=vital-signs' },
  { method: 'GET', url: 'Patient/12345/Condition?clinical-status=active' }
]);

bundle.entry.forEach((entry, index) => {
  console.log(`Response ${index}: ${entry.response.status}`);
  console.log(entry.resource);
});

トランザクションリクエスト

複数のリクエストをアトミックな単位として実行します。

const transactionRequest = async (requests) => {
  const bundle = {
    resourceType: 'Bundle',
    type: 'transaction',
    entry: requests.map(req => ({
      resource: req.resource,
      request: {
        method: req.method,
        url: req.url
      }
    }))
  };

  const response = await fhirRequest('', {
    method: 'POST',
    body: JSON.stringify(bundle)
  });

  return response;
};

// 使用例 - 患者と関連リソースの作成
const transaction = await transactionRequest([
  {
    method: 'POST',
    url: 'Patient',
    resource: {
      resourceType: 'Patient',
      name: [{ family: 'Doe', given: ['Jane'] }],
      gender: 'female',
      birthDate: '1990-01-01'
    }
  },
  {
    method: 'POST',
    url: 'Condition',
    resource: {
      resourceType: 'Condition',
      clinicalStatus: { coding: [{ code: 'active' }] },
      code: { coding: [{ system: 'http://snomed.info/sct', code: '38341003' }] },
      subject: { reference: 'Patient/-1' } // 最初のリソースへの参照
    }
  }
]);

サブスクリプションとWebhook

FHIRサブスクリプション (R4B+)

リソースの変更をサブスクライブします。

const createSubscription = async (subscriptionData) => {
  const subscription = {
    resourceType: 'Subscription',
    status: 'requested',
    criteria: subscriptionData.criteria,
    reason: subscriptionData.reason,
    channel: {
      type: 'rest-hook',
      endpoint: subscriptionData.endpoint,
      payload: 'application/fhir+json'
    }
  };

  const response = await fhirRequest('/Subscription', {
    method: 'POST',
    body: JSON.stringify(subscription)
  });

  return response;
};

// 使用例 - 新しい検査結果をサブスクライブ
const subscription = await createSubscription({
  criteria: 'DiagnosticReport?category=laboratory&patient=12345',
  reason: 'Monitor patient lab results',
  endpoint: 'https://myapp.com/webhooks/fhir'
});

FHIR Webhookの処理

const express = require('express');
const app = express();

app.post('/webhooks/fhir', express.json({ type: 'application/fhir+json' }), async (req, res) => {
  const notification = req.body;

  // サブスクリプション参照を検証
  if (notification.subscription !== expectedSubscription) {
    return res.status(401).send('Unauthorized');
  }

  // 通知を処理
  if (notification.event?.resourceType === 'DiagnosticReport') {
    const reportId = notification.event.resourceId;
    const report = await fhirRequest(`/DiagnosticReport/${reportId}`);

    // 新しい検査結果を処理
    await processLabResult(report);
  }

  res.status(200).send('OK');
});

一般的な問題のトラブルシューティング

問題: 401 Unauthorized

症状: 「Unauthorized」または「Invalid token」エラーが発生する。

解決策:

  1. トークンの有効期限が切れていないか確認する
  2. トークンのスコープが要求されたリソースを含んでいるか確認する
  3. Authorization: Bearer {token}ヘッダーが存在することを確認する
  4. FHIRサーバーのURLがトークンのオーディエンスと一致しているか確認する

問題: 403 Forbidden

症状: トークンは有効だがアクセスが拒否される。

解決策:

  1. ユーザーが要求されたリソースに対する権限を持っているか確認する
  2. 患者コンテキストが一致しているか確認する(患者スコープのトークンの場合)
  3. SMARTスコープが要求された操作を含んでいるか確認する
  4. リソースレベルのアクセス制御を確認する

問題: 404 Not Found

症状: リソースが存在しない、またはエンドポイントが間違っている。

解決策:

  1. リソースIDが正しいか確認する
  2. FHIRベースURLが正しいか確認する
  3. リソースタイプがサーバーによってサポートされているか確認する
  4. バージョン固有のエンドポイント(R4とR4Bなど)を確認する

問題: 422 Unprocessable Entity

症状: 作成/更新時に検証エラーが発生する。

解決策:

// 検証エラーを解析
const error = await response.json();
error.issue?.forEach(issue => {
  console.error(`Severity: ${issue.severity}`);
  console.error(`Location: ${issue.expression?.join('.')}`);
  console.error(`Message: ${issue.details?.text}`);
});

一般的な原因:

本番デプロイチェックリスト

本番稼働前に:

FHIR検証

const { FhirValidator } = require('fhir-validator');

const validator = new FhirValidator('4.0.1');

const validateResource = async (resource) => {
  const validationResult = await validator.validate(resource);

  if (!validationResult.valid) {
    validationResult.issues.forEach(issue => {
      console.error(`Validation Error: ${issue.message}`);
      console.error(`Location: ${issue.path}`);
    });
    throw new Error('Resource validation failed');
  }

  return true;
};

// 作成/更新前の使用例
await validateResource(patientResource);

実世界のユースケース

患者ポータル統合

医療システムが患者ポータルを構築しました。

主要な実装:

臨床意思決定支援

ケア管理プラットフォームがCDSを追加しました。

主要な実装:

集団健康分析

保険会社が集団健康ダッシュボードを構築しました。

主要な実装:

結論

HL7 FHIRは、現代の医療相互運用性の基盤を提供します。主なポイント:

button

FAQ

HL7 FHIRは何のために使われますか?

FHIRは、電子カルテ、患者ポータル、モバイルアプリ、その他のヘルスITシステム間で医療データを標準化された方法で交換することを可能にします。一般的なユースケースには、患者アクセスアプリ、臨床意思決定支援、集団健康、ケア連携などがあります。

FHIRを始めるにはどうすればよいですか?

まず、公開されているFHIRサーバー(HAPI FHIRテストサーバーなど)にアクセスするか、クラウドFHIRサービス(Azure API for FHIR、AWS HealthLakeなど)を設定します。リソースの読み取りや検索パラメーターの使用を練習してください。

HL7 v2とFHIRの違いは何ですか?

HL7 v2は、イベント駆動型のデータ交換のためにパイプ区切りのメッセージ(ADT、ORM、ORU)を使用します。FHIRは、リソースベースのアクセスにJSON/XMLを使用したRESTful APIを使用します。FHIRは実装が容易で、最新のWeb/モバイルアプリにより適しています。

FHIRはHIPAAに準拠していますか?

FHIR自体はデータ形式の標準です。HIPAA準拠は、実装に依存します。暗号化、認証、アクセス制御、監査ログなどが必要です。セキュアなアクセスには、SMART on FHIRを使用したOAuth 2.0を使用してください。

SMARTスコープとは何ですか?

SMARTスコープは、FHIRリソースに対するきめ細やかなアクセス許可(例:patient/Observation.readuser/*.read)を定義します。アプリが必要とするスコープのみを要求してください。

FHIRでリソースを検索するにはどうすればよいですか?

クエリパラメーターを使ったGETリクエストを使用します。例:/Patient?name=Smith&birthdate=ge1980-01-01。FHIRは修飾子(:exact:contains)やプレフィックス(gtltgele)をサポートしています。

Bulk FHIRとは何ですか?

Bulk FHIR($export)は、NDJSON形式で大規模なデータセットを非同期でエクスポートすることを可能にします。集団健康、分析、データウェアハウジングなどで使用されます。

FHIRのバージョン管理はどのように行いますか?

特定のFHIRバージョン(R4推奨)をターゲットにし、バージョン固有のエンドポイントを使用します。サポートされているバージョンとリソースについては、CapabilityStatementを確認してください。

FHIRをカスタムフィールドで拡張できますか?

はい、FHIR拡張機能を使用してカスタムデータ要素を追加できます。拡張機能をImplementation Guideで定義し、広く共有する場合はHL7に登録してください。

FHIR開発に役立つツールは何ですか?

一般的なツールには、HAPI FHIR(オープンソースサーバー)、FHIRバリデーター、Postmanコレクション、APIテストとドキュメント化のためのApidogがあります。

ApidogでAPIデザイン中心のアプローチを取る

APIの開発と利用をよりシンプルなことにする方法を発見できる