Cara Menggunakan HL7 FHIR API: Panduan Integrasi Sistem Kesehatan Lengkap (2026)

Ashley Innocent

Ashley Innocent

25 March 2026

Cara Menggunakan HL7 FHIR API: Panduan Integrasi Sistem Kesehatan Lengkap (2026)

Apidog untuk Perusahaan

Penerapan On-Premises

SSO & RBAC

Sesuai SOC 2

Jelajahi Apidog Enterprise

Inti Sari

HL7 FHIR (Fast Healthcare Interoperability Resources) adalah standar modern untuk pertukaran data layanan kesehatan, menggunakan API RESTful dengan respons JSON/XML. Ini menyediakan sumber daya terstandardisasi untuk pasien, observasi, obat-obatan, dan lainnya, dengan autentikasi OAuth 2.0 dan SMART on FHIR untuk integrasi aplikasi. Panduan ini mencakup arsitektur FHIR, tipe sumber daya, parameter pencarian, autentikasi, dan strategi implementasi produksi.

Pendahuluan

Fragmentasi data layanan kesehatan merugikan sistem layanan kesehatan AS sebesar $30 miliar setiap tahun. Bagi pengembang yang membangun aplikasi layanan kesehatan, integrasi API HL7 FHIR bukanlah pilihan—ini adalah standar industri yang diwajibkan oleh CMS dan diadopsi oleh Epic, Cerner, serta semua vendor EHR utama.

Inilah kenyataannya: penyedia layanan yang menggunakan aplikasi berkemampuan FHIR mengurangi waktu koordinasi perawatan sebesar 40% dan menghilangkan 85% permintaan catatan berbasis faks. Integrasi API FHIR yang solid memungkinkan pertukaran data yang lancar di seluruh EHR, portal pasien, dan platform koordinasi perawatan.

Panduan ini membahas proses integrasi API HL7 FHIR secara lengkap. Anda akan mempelajari arsitektur FHIR, tipe sumber daya, parameter pencarian, autentikasi OAuth 2.0, integrasi SMART on FHIR, dan strategi penerapan produksi. Pada akhirnya, Anda akan memiliki integrasi FHIR yang siap produksi.

💡
Apidog menyederhanakan integrasi API layanan kesehatan. Uji endpoint FHIR, validasi skema sumber daya, debug alur autentikasi, dan dokumentasikan spesifikasi API dalam satu ruang kerja. Impor Panduan Implementasi FHIR, respons tiruan, dan bagikan skenario pengujian dengan tim Anda.
tombol

Apa Itu HL7 FHIR?

FHIR (Fast Healthcare Interoperability Resources) adalah kerangka kerja standar untuk pertukaran informasi layanan kesehatan secara elektronik. Dikembangkan oleh Health Level Seven International (HL7), FHIR menggunakan teknologi web modern termasuk API RESTful, JSON, XML, dan OAuth 2.0.

Bagaimana HL7 FHIR bekerja

Tipe Sumber Daya FHIR

FHIR mendefinisikan lebih dari 140 tipe sumber daya. Sumber daya inti meliputi:

Sumber Daya Tujuan Kasus Penggunaan Umum
Pasien Demografi Pencarian pasien, pendaftaran
Praktisi Info penyedia Direktori, penjadwalan
Perjumpaan Kunjungan/penerimaan Episode perawatan, penagihan
Observasi Data klinis Tanda vital, hasil lab, penilaian
Kondisi Masalah/diagnosis Daftar masalah, perencanaan perawatan
Permintaan Obat Resep Resep elektronik, riwayat obat
AlergiIntoleransi Alergi Pemeriksaan keamanan, peringatan
Imunisasi Vaksinasi Catatan imunisasi
Laporan Diagnostik Laporan lab/pencitraan Pengiriman hasil
Referensi Dokumen Dokumen klinis CCD, ringkasan keluar

Arsitektur API FHIR

FHIR menggunakan struktur API RESTful:

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

Perbandingan Versi FHIR

Versi Status Kasus Penggunaan
R4 (4.0.1) STU Saat Ini Implementasi produksi
R4B (4.3) Implementasi Uji Coba Pengguna awal
R5 (5.0.0) Draf STU Implementasi masa depan
DSTU2 Ditinggalkan Hanya sistem lama

CMS mewajibkan EHR Bersertifikat untuk mendukung FHIR R4 untuk API Akses Pasien dan Akses Penyedia.

Memulai: Akses Server FHIR

Langkah 1: Pilih Server FHIR Anda

Pilihan untuk penerapan server FHIR:

Server Tipe Biaya Terbaik Untuk
Azure API for FHIR Terkelola Bayar-per-penggunaan Perusahaan, pengguna Azure
AWS HealthLake Terkelola Bayar-per-penggunaan Lingkungan AWS
Google Cloud Healthcare API Terkelola Bayar-per-penggunaan Lingkungan GCP
HAPI FHIR Sumber Terbuka Dihosting sendiri Penerapan kustom
Epic FHIR Server Komersial Pelanggan Epic Integrasi EHR Epic
Cerner Ignite FHIR Komersial Pelanggan Cerner Integrasi EHR Cerner

Langkah 2: Dapatkan Kredensial Server

Untuk layanan FHIR cloud:

# Azure API for FHIR
# 1. Buat Layanan FHIR di Azure Portal
# 2. Konfigurasi autentikasi (OAuth 2.0 atau AAD)
# 3. Dapatkan endpoint FHIR: https://{nama-layanan}.azurehealthcareapis.com
# 4. Daftarkan aplikasi klien untuk OAuth

# AWS HealthLake
# 1. Buat Data Store di AWS Console
# 2. Konfigurasi peran IAM
# 3. Dapatkan endpoint: https://healthlake.{wilayah}.amazonaws.com

Langkah 3: Pahami Operasi RESTful FHIR

FHIR mendukung metode HTTP standar:

Operasi Metode HTTP Endpoint Deskripsi
Baca GET /{resourceType}/{id} Dapatkan sumber daya spesifik
Cari GET /{resourceType}?param=value Cari sumber daya
Buat POST /{resourceType} Buat sumber daya baru
Perbarui PUT /{resourceType}/{id} Ganti sumber daya
Tambal PATCH /{resourceType}/{id} Pembaruan sebagian
Hapus DELETE /{resourceType}/{id} Hapus sumber daya
Riwayat GET /{resourceType}/{id}/_history Versi sumber daya

Langkah 4: Lakukan Panggilan FHIR Pertama Anda

Uji konektivitas:

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

Respons yang diharapkan:

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

Operasi Inti FHIR

Membaca Sumber Daya Pasien

Ambil pasien berdasarkan 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();
};

// Baca pasien berdasarkan ID
const getPatient = async (patientId) => {
  const patient = await fhirRequest(`/Patient/${patientId}`);
  return patient;
};

// Penggunaan
const patient = await getPatient('12345');
console.log(`Pasien: ${patient.name[0].given[0]} ${patient.name[0].family}`);
console.log(`Tanggal Lahir: ${patient.birthDate}`);
console.log(`Jenis Kelamin: ${patient.gender}`);

Struktur Sumber Daya Pasien

{
  "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"
    }
  ]
}

Mencari Sumber Daya

Cari pasien berdasarkan nama:

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

  // Tambahkan parameter pencarian
  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;
};

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

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

Parameter Pencarian Umum

Sumber Daya Parameter Pencarian Contoh
Pasien nama, tanggal lahir, pengidentifikasi, jenis kelamin, telepon, email ?name=Smith&birthdate=1985-06-15
Observasi pasien, kode, tanggal, kategori, status ?patient=123&code=8480-6&date=ge2026-01-01
Kondisi pasien, status-klinis, kategori, tanggal-mulai ?patient=123&clinical-status=active
Permintaan Obat pasien, status, tujuan, obat ?patient=123&status=active
Perjumpaan pasien, tanggal, status, kelas ?patient=123&date=ge2026-01-01
Laporan Diagnostik pasien, kategori, tanggal, status ?patient=123&category=laboratory

Pengubah Pencarian

Pengubah Deskripsi Contoh
:exact Kecocokan persis name:exact=Smith
:contains Mengandung name:contains=smi
:missing Memiliki/tidak memiliki nilai phone:missing=true
: (awalan) Operator awalan birthdate=ge1980-01-01

Awalan Pencarian untuk Tanggal dan Angka

Awalan Arti Contoh
eq Sama dengan birthdate=eq1985-06-15
ne Tidak sama dengan birthdate=ne1985-06-15
gt Lebih besar dari birthdate=gt1980-01-01
lt Lebih kecil dari birthdate=lt1990-01-01
ge Lebih besar atau sama dengan birthdate=ge1980-01-01
le Lebih kecil atau sama dengan birthdate=le1990-01-01
sa Dimulai setelah date=sa2026-01-01
eb Berakhir sebelum date=eb2026-12-31

Bekerja dengan Data Klinis

Membuat Observasi (Tanda Vital)

Catat tanda vital:

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, // mis., '8480-6' untuk Tekanan Darah Sistolik
        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;
};

// Penggunaan - Catat tekanan darah
const systolicBP = await createObservation({
  patientId: '12345',
  code: '8480-6',
  display: 'Tekanan darah sistolik',
  value: 120,
  unit: 'mmHg',
  ucumCode: 'mm[Hg]',
  performerId: '67890'
});

console.log(`Observasi dibuat: ${systolicBP.id}`);

Kode LOINC Umum

Kode Tampilan Kategori
8480-6 Tekanan darah sistolik Tanda vital
8462-4 Tekanan darah diastolik Tanda vital
8867-4 Denyut jantung Tanda vital
8310-5 Suhu tubuh Tanda vital
8302-2 Tinggi badan Tanda vital
29463-7 Berat badan Tanda vital
8871-5 Laju pernapasan Tanda vital
2339-0 Glukosa [Massa/volume] Laboratorium
4548-4 Hemoglobin A1c Laboratorium
2093-3 Kolesterol [Massa/volume] Laboratorium

Membuat Kondisi (Entri Daftar Masalah)

Tambahkan diagnosis ke daftar masalah:

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;
};

// Penggunaan - Tambahkan diabetes ke daftar masalah
const diabetes = await createCondition({
  patientId: '12345',
  sctCode: '44054006',
  display: 'Diabetes Mellitus Tipe 2',
  status: 'active',
  category: 'problem-list-item',
  onsetDate: '2024-01-15'
});

Kode SNOMED CT Umum

Kode Tampilan Kategori
44054006 Diabetes Mellitus Tipe 2 Masalah
38341003 Hipertensi Masalah
195967001 Asma Masalah
13645005 Penyakit Paru Obstruktif Kronis Masalah
35489007 Gangguan Depresif Masalah
22298006 Infark Miokard Masalah
26929004 Penyakit Alzheimer Masalah
396275006 Osteoartritis Masalah

Mengambil Obat Pasien

Dapatkan permintaan obat aktif:

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

  return response;
};

// Penggunaan
const medications = await getPatientMedications('12345');

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

Mengambil Hasil Lab

Dapatkan laporan diagnostik dan observasi:

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;
};

// Dapatkan tes lab spesifik (misalnya, HbA1c)
const getLabValue = async (patientId, loincCode) => {
  const params = new URLSearchParams({
    patient: patientId,
    code: loincCode
  });

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

// Penggunaan - Dapatkan hasil 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(`Tanggal: ${obs.effectiveDateTime}`);
});

OAuth 2.0 dan SMART on FHIR

Memahami Autentikasi FHIR

Server FHIR menggunakan OAuth 2.0 dengan OpenID Connect:

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│    Klien    │───▶│   Server    │───▶│   Server    │
│   (Aplikasi)│    │ Autentikasi │    │    FHIR     │
└─────────────┘    └─────────────┘    └─────────────┘
     │                    │                    │
     │ 1. Permintaan Auth │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │ 2. Login Pengguna  │                    │
     │◀───────────────────│                    │
     │                    │                    │
     │ 3. Kode Auth       │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │ 4. Permintaan Token│                    │
     │───────────────────▶│                    │
     │                    │  5. Token + ID     │
     │◀───────────────────│                    │
     │                    │                    │
     │ 6. Permintaan API  │                    │
     │────────────────────────────────────────▶│
     │                    │                    │
     │ 7. Data FHIR       │                    │
     │◀────────────────────────────────────────│

Peluncuran Aplikasi SMART on FHIR

Implementasikan peluncuran aplikasi SMART:

const crypto = require('crypto');

class SMARTClient {
  constructor(config) {
    this.clientId = config.clientId;
    this.redirectUri = config.redirectUri;
    this.issuer = config.issuer; // URL server FHIR
    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();

    // Simpan codeVerifier untuk pertukaran token
    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
    };
  }
}

// Penggunaan
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'
  ]
});

// Arahkan pengguna ke URL autentikasi
const state = crypto.randomBytes(16).toString('hex');
const authUrl = smartClient.buildAuthUrl(state);
console.log(`Arahkan ke: ${authUrl}`);

Lingkup SMART yang Diperlukan

Lingkup Izin Kasus Penggunaan
openid Autentikasi OIDC Diperlukan untuk semua aplikasi
profile Info profil pengguna Direktori penyedia
patient/Patient.read Baca demografi pasien Pencarian pasien
patient/Observation.read Baca observasi Tanda vital, lab
patient/Condition.read Baca kondisi Daftar masalah
patient/MedicationRequest.read Baca obat-obatan Riwayat obat
patient/*.read Baca semua sumber daya pasien Data pasien lengkap
user/*.read Baca semua sumber daya yang dapat diakses Tampilan penyedia
offline_access Token penyegaran Sesi jangka panjang

Membuat Permintaan FHIR yang Diautentikasi

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()}`);
  }
}

// Penggunaan setelah callback OAuth
const fhirClient = new FHIRClient(tokens.accessToken, 'https://fhir.epic.com');
const patient = await fhirClient.getPatient(tokens.patientId);

Operasi Batch dan Transaksi

Permintaan Batch

Jalankan beberapa permintaan independen:

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;
};

// Penggunaan - Ambil beberapa sumber daya
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(`Respons ${index}: ${entry.response.status}`);
  console.log(entry.resource);
});

Permintaan Transaksi

Jalankan beberapa permintaan sebagai unit atomik:

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;
};

// Penggunaan - Buat pasien dan sumber daya terkait
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' } // Referensi ke sumber daya pertama
    }
  }
]);

Langganan dan Webhook

Langganan FHIR (R4B+)

Berlangganan perubahan sumber daya:

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;
};

// Penggunaan - Berlangganan hasil lab baru
const subscription = await createSubscription({
  criteria: 'DiagnosticReport?category=laboratory&patient=12345',
  reason: 'Pantau hasil lab pasien',
  endpoint: 'https://myapp.com/webhooks/fhir'
});

Menangani Webhook FHIR

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

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

  // Verifikasi referensi langganan
  if (notification.subscription !== expectedSubscription) {
    return res.status(401).send('Tidak Sah');
  }

  // Proses notifikasi
  if (notification.event?.resourceType === 'DiagnosticReport') {
    const reportId = notification.event.resourceId;
    const report = await fhirRequest(`/DiagnosticReport/${reportId}`);

    // Proses hasil lab baru
    await processLabResult(report);
  }

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

Memecahkan Masalah Umum

Masalah: 401 Tidak Sah

Gejala: Mendapatkan kesalahan “Tidak Sah” atau “Token tidak valid”.

Solusi:

  1. Verifikasi token belum kedaluwarsa
  2. Periksa lingkup token mencakup sumber daya yang diminta
  3. Pastikan header Authorization: Bearer {token} ada
  4. Verifikasi URL server FHIR sesuai dengan audiens token

Masalah: 403 Dilarang

Gejala: Token valid tetapi akses ditolak.

Solusi:

  1. Periksa pengguna memiliki izin untuk sumber daya yang diminta
  2. Verifikasi konteks pasien sesuai (untuk token lingkup-pasien)
  3. Pastikan lingkup SMART mencakup operasi yang diminta
  4. Periksa kontrol akses tingkat sumber daya

Masalah: 404 Tidak Ditemukan

Gejala: Sumber daya tidak ada atau endpoint salah.

Solusi:

  1. Verifikasi ID sumber daya benar
  2. Periksa URL dasar FHIR benar
  3. Pastikan tipe sumber daya didukung oleh server
  4. Verifikasi endpoint spesifik versi (R4 vs R4B)

Masalah: 422 Entitas Tidak Dapat Diproses

Gejala: Kesalahan validasi saat membuat/memperbarui.

Solusi:

// Uraikan kesalahan validasi
const error = await response.json();
error.issue?.forEach(issue => {
  console.log(`Tingkat Keparahan: ${issue.severity}`);
  console.log(`Lokasi: ${issue.expression?.join('.')}`);
  console.log(`Pesan: ${issue.details?.text}`);
});

Penyebab umum:

Daftar Periksa Penerapan Produksi

Sebelum tayang:

Validasi 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(`Kesalahan Validasi: ${issue.message}`);
      console.error(`Lokasi: ${issue.path}`);
    });
    throw new Error('Validasi sumber daya gagal');
  }

  return true;
};

// Penggunaan sebelum membuat/memperbarui
await validateResource(patientResource);

Kasus Penggunaan Dunia Nyata

Integrasi Portal Pasien

Sistem kesehatan membangun portal pasien:

Implementasi kunci:

Dukungan Keputusan Klinis

Platform manajemen perawatan menambahkan CDS:

Implementasi kunci:

Analitik Kesehatan Populasi

Pembayar membangun dasbor kesehatan populasi:

Implementasi kunci:

Kesimpulan

HL7 FHIR menyediakan fondasi untuk interoperabilitas layanan kesehatan modern. Poin-poin penting:

tombol

Bagian FAQ

Untuk apa HL7 FHIR digunakan?

FHIR memungkinkan pertukaran data layanan kesehatan yang terstandardisasi antara EHR, portal pasien, aplikasi seluler, dan sistem IT kesehatan lainnya. Kasus penggunaan umum meliputi aplikasi akses pasien, dukungan keputusan klinis, kesehatan populasi, dan koordinasi perawatan.

Bagaimana cara memulai dengan FHIR?

Mulailah dengan mengakses server FHIR publik (seperti server uji HAPI FHIR) atau siapkan layanan FHIR cloud (Azure API for FHIR, AWS HealthLake). Berlatih membaca sumber daya dan menggunakan parameter pencarian.

Apa perbedaan antara HL7 v2 dan FHIR?

HL7 v2 menggunakan pesan yang dibatasi tanda pipa (ADT, ORM, ORU) untuk pertukaran data berbasis peristiwa. FHIR menggunakan API RESTful dengan JSON/XML untuk akses berbasis sumber daya. FHIR lebih mudah diimplementasikan dan lebih cocok untuk aplikasi web/seluler modern.

Apakah FHIR patuh HIPAA?

FHIR sendiri adalah standar format data. Kepatuhan HIPAA tergantung pada implementasi: enkripsi, autentikasi, kontrol akses, dan pencatatan audit. Gunakan OAuth 2.0 dengan SMART on FHIR untuk akses yang aman.

Apa itu lingkup SMART?

Lingkup SMART mendefinisikan izin akses granular untuk sumber daya FHIR (misalnya, patient/Observation.read, user/*.read). Minta hanya lingkup yang dibutuhkan aplikasi Anda.

Bagaimana cara mencari sumber daya di FHIR?

Gunakan permintaan GET dengan parameter kueri: /Patient?name=Smith&birthdate=ge1980-01-01. FHIR mendukung pengubah (:exact, :contains) dan awalan (gt, lt, ge, le).

Apa itu Bulk FHIR?

Bulk FHIR ($export) memungkinkan ekspor asinkron dataset besar dalam format NDJSON. Digunakan untuk kesehatan populasi, analitik, dan gudang data.

Bagaimana cara menangani pembuatan versi FHIR?

Targetkan versi FHIR tertentu (R4 direkomendasikan) dan gunakan endpoint spesifik versi. Periksa CapabilityStatement untuk versi dan sumber daya yang didukung.

Bisakah saya memperluas FHIR dengan bidang kustom?

Ya, gunakan ekstensi FHIR untuk menambahkan elemen data kustom. Definisikan ekstensi dalam Panduan Implementasi Anda dan daftarkan dengan HL7 jika dibagikan secara luas.

Alat apa yang membantu pengembangan FHIR?

Alat populer meliputi HAPI FHIR (server sumber terbuka), validator FHIR, koleksi Postman, dan Apidog untuk pengujian dan dokumentasi API.

Mengembangkan API dengan Apidog

Apidog adalah alat pengembangan API yang membantu Anda mengembangkan API dengan lebih mudah dan efisien.