HL7 FHIR API Nutzung: Umfassende Anleitung zur Gesundheitswesen Integration (2026)

Ashley Innocent

Ashley Innocent

25 March 2026

HL7 FHIR API Nutzung: Umfassende Anleitung zur Gesundheitswesen Integration (2026)

Apidog für Unternehmen

On-Premises Bereitstellung

SSO & RBAC

SOC 2 konform

Apidog Enterprise entdecken

TL;DR

HL7 FHIR (Fast Healthcare Interoperability Resources) ist der moderne Standard für den Austausch von Gesundheitsdaten, der RESTful APIs mit JSON/XML-Antworten nutzt. Es bietet standardisierte Ressourcen für Patienten, Beobachtungen, Medikamente und mehr, mit OAuth 2.0-Authentifizierung und SMART on FHIR für die App-Integration. Dieser Leitfaden behandelt die FHIR-Architektur, Ressourcentypen, Suchparameter, Authentifizierung und Implementierungsstrategien für die Produktion.

Einführung

Die Fragmentierung von Gesundheitsdaten kostet das US-Gesundheitssystem jährlich 30 Milliarden Dollar. Für Entwickler, die Gesundheitsanwendungen erstellen, ist die Integration der HL7 FHIR API keine Option, sondern der Industriestandard, der von CMS vorgeschrieben und von Epic, Cerner sowie allen großen EHR-Anbietern übernommen wird.

Hier ist die Realität: Anbieter, die FHIR-fähige Apps nutzen, reduzieren die Zeit für die Versorgungskoordination um 40 % und eliminieren 85 % der faxbasierten Anfragen nach Akten. Eine solide FHIR API-Integration ermöglicht einen nahtlosen Datenaustausch über EHRs, Patientenportale und Plattformen zur Versorgungskoordination hinweg.

Dieser Leitfaden führt Sie durch den gesamten Integrationsprozess der HL7 FHIR API. Sie lernen die FHIR-Architektur, Ressourcentypen, Suchparameter, OAuth 2.0-Authentifizierung, SMART on FHIR-Integration und Bereitstellungsstrategien für die Produktion kennen. Am Ende verfügen Sie über eine produktionsreife FHIR-Integration.

💡
Apidog vereinfacht die Integration von Gesundheits-APIs. Testen Sie FHIR-Endpunkte, validieren Sie Ressourcenschemata, debuggen Sie Authentifizierungsabläufe und dokumentieren Sie API-Spezifikationen in einem einzigen Arbeitsbereich. Importieren Sie FHIR Implementation Guides, mocken Sie Antworten und teilen Sie Testszenarien mit Ihrem Team.
Schaltfläche

Was ist HL7 FHIR?

FHIR (Fast Healthcare Interoperability Resources) ist ein Standard-Framework für den elektronischen Austausch von Gesundheitsinformationen. Entwickelt von Health Level Seven International (HL7), verwendet FHIR moderne Webtechnologien wie RESTful APIs, JSON, XML und OAuth 2.0.

image-245

FHIR-Ressourcentypen

FHIR definiert über 140 Ressourcentypen. Zu den Kernressourcen gehören:

Ressource Zweck Häufige Anwendungsfälle
Patient Demografische Daten Patientensuche, Registrierung
Practitioner Anbieterinformationen Verzeichnis, Terminplanung
Encounter Besuche/Aufnahmen Behandlungsepisoden, Abrechnung
Observation Klinische Daten Vitalwerte, Laborergebnisse, Beurteilungen
Condition Probleme/Diagnosen Problemlisten, Behandlungsplanung
MedicationRequest Verschreibungen E-Rezept, Medikationshistorie
AllergyIntolerance Allergien Sicherheitsprüfungen, Warnungen
Immunization Impfungen Impfprotokolle
DiagnosticReport Labor-/Bildgebungsberichte Ergebnisübermittlung
DocumentReference Klinische Dokumente CCD, Entlassungszusammenfassungen

FHIR API-Architektur

FHIR verwendet eine RESTful API-Struktur:

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

FHIR-Versionen im Vergleich

Version Status Anwendungsfall
R4 (4.0.1) Aktueller STU Produktionsimplementierungen
R4B (4.3) Testimplementierung Frühe Anwender
R5 (5.0.0) Entwurf STU Zukünftige Implementierungen
DSTU2 Veraltet Nur für Legacy-Systeme

CMS verlangt von zertifizierten EHRs die Unterstützung von FHIR R4 für Patient Access und Provider Access APIs.

Erste Schritte: FHIR-Server-Zugang

Schritt 1: Wählen Sie Ihren FHIR-Server

Optionen für die Bereitstellung eines FHIR-Servers:

Server Typ Kosten Am besten für
Azure API for FHIR Verwaltet Pay-per-Use Unternehmen, Azure-Nutzer
AWS HealthLake Verwaltet Pay-per-Use AWS-Umgebungen
Google Cloud Healthcare API Verwaltet Pay-per-Use GCP-Umgebungen
HAPI FHIR Open Source Selbst gehostet Benutzerdefinierte Bereitstellungen
Epic FHIR Server Kommerziell Epic-Kunden Epic EHR-Integration
Cerner Ignite FHIR Kommerziell Cerner-Kunden Cerner EHR-Integration

Schritt 2: Server-Anmeldeinformationen erhalten

Für Cloud-FHIR-Dienste:

# Azure API für FHIR
# 1. FHIR-Dienst im Azure-Portal erstellen
# 2. Authentifizierung konfigurieren (OAuth 2.0 oder AAD)
# 3. FHIR-Endpunkt abrufen: https://{service-name}.azurehealthcareapis.com
# 4. Client-App für OAuth registrieren

# AWS HealthLake
# 1. Datenspeicher in der AWS-Konsole erstellen
# 2. IAM-Rollen konfigurieren
# 3. Endpunkt abrufen: https://healthlake.{region}.amazonaws.com

Schritt 3: FHIR RESTful-Operationen verstehen

FHIR unterstützt Standard-HTTP-Methoden:

Operation HTTP-Methode Endpunkt Beschreibung
Lesen GET /{resourceType}/{id} Spezifische Ressource abrufen
Suchen GET /{resourceType}?param=value Ressourcen suchen
Erstellen POST /{resourceType} Neue Ressource erstellen
Aktualisieren PUT /{resourceType}/{id} Ressource ersetzen
Patchen PATCH /{resourceType}/{id} Partielle Aktualisierung
Löschen DELETE /{resourceType}/{id} Ressource entfernen
Historie GET /{resourceType}/{id}/_history Ressourcenversionen

Schritt 4: Ihren ersten FHIR-Aufruf tätigen

Konnektivität testen:

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

Erwartete Antwort:

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

FHIR-Kernoperationen

Eine Patientenressource lesen

Patient nach ID abrufen:

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-Fehler: ${error.issue?.[0]?.details?.text || response.statusText}`);
  }

  return response.json();
};

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

// Verwendung
const patient = await getPatient('12345');
console.log(`Patient: ${patient.name[0].given[0]} ${patient.name[0].family}`);
console.log(`Geburtsdatum: ${patient.birthDate}`);
console.log(`Geschlecht: ${patient.gender}`);

Struktur der Patientenressource

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

Suchen nach Ressourcen

Patienten nach Namen suchen:

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

  // Suchparameter hinzufügen
  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;
};

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

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

Häufige Suchparameter

Ressource Suchparameter Beispiel
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

Suchmodifikatoren

Modifikator Beschreibung Beispiel
:exact Exakte Übereinstimmung name:exact=Smith
:contains Enthält name:contains=smi
:missing Hat/Fehlender Wert phone:missing=true
: (Präfix) Präfix-Operatoren birthdate=ge1980-01-01

Suchpräfixe für Daten und Zahlen

Präfix Bedeutung Beispiel
eq Gleich birthdate=eq1985-06-15
ne Ungleich birthdate=ne1985-06-15
gt Größer als birthdate=gt1980-01-01
lt Kleiner als birthdate=lt1990-01-01
ge Größer oder gleich birthdate=ge1980-01-01
le Kleiner oder gleich birthdate=le1990-01-01
sa Beginnt nach date=sa2026-01-01
eb Endet vor date=eb2026-12-31

Arbeiten mit klinischen Daten

Eine Beobachtung erstellen (Vitalwerte)

Vitalwerte aufzeichnen:

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, // z.B. '8480-6' für systolischen Blutdruck
        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;
};

// Verwendung - Blutdruck aufzeichnen
const systolicBP = await createObservation({
  patientId: '12345',
  code: '8480-6',
  display: 'Systolischer Blutdruck',
  value: 120,
  unit: 'mmHg',
  ucumCode: 'mm[Hg]',
  performerId: '67890'
});

console.log(`Beobachtung erstellt: ${systolicBP.id}`);

Häufige LOINC-Codes

Code Anzeige Kategorie
8480-6 Systolischer Blutdruck Vitalwerte
8462-4 Diastolischer Blutdruck Vitalwerte
8867-4 Herzfrequenz Vitalwerte
8310-5 Körpertemperatur Vitalwerte
8302-2 Körpergröße Vitalwerte
29463-7 Körpergewicht Vitalwerte
8871-5 Atemfrequenz Vitalwerte
2339-0 Glukose [Masse/Volumen] Labor
4548-4 Hämoglobin A1c Labor
2093-3 Cholesterin [Masse/Volumen] Labor

Eine Bedingung erstellen (Eintrag in der Problemliste)

Diagnose zur Problemliste hinzufügen:

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

// Verwendung - Diabetes zur Problemliste hinzufügen
const diabetes = await createCondition({
  patientId: '12345',
  sctCode: '44054006',
  display: 'Diabetes mellitus Typ 2',
  status: 'active',
  category: 'problem-list-item',
  onsetDate: '2024-01-15'
});

Häufige SNOMED CT-Codes

Code Anzeige Kategorie
44054006 Diabetes mellitus Typ 2 Problem
38341003 Hypertonie Problem
195967001 Asthma Problem
13645005 Chronisch obstruktive Lungenerkrankung Problem
35489007 Depressive Störung Problem
22298006 Myokardinfarkt Problem
26929004 Alzheimer-Krankheit Problem
396275006 Arthrose Problem

Medikationen des Patienten abrufen

Aktive Medikationsanfragen abrufen:

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

  return response;
};

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

Laborergebnisse abrufen

Diagnoseberichte und Beobachtungen abrufen:

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

// Spezifischen Labortest abrufen (z.B. HbA1c)
const getLabValue = async (patientId, loincCode) => {
  const params = new URLSearchParams({
    patient: patientId,
    code: loincCode
  });

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

// Verwendung - HbA1c-Ergebnisse abrufen
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(`Datum: ${obs.effectiveDateTime}`);
});

OAuth 2.0 und SMART on FHIR

FHIR-Authentifizierung verstehen

FHIR-Server verwenden OAuth 2.0 mit OpenID Connect:

┌─────────────┐    ┌─────────────┐    ┌─────────────┐
│   Client    │───▶│   Auth      │───▶│   FHIR      │
│   (App)     │    │   Server    │    │   Server    │
└─────────────┘    └─────────────┘    └─────────────┘
     │                    │                    │
     │  1. Auth-Anfrage   │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │  2. Benutzer-Login │                    │
     │◀───────────────────│                    │
     │                    │                    │
     │  3. Auth-Code      │                    │
     │───────────────────▶│                    │
     │                    │                    │
     │  4. Token-Anfrage  │                    │
     │───────────────────▶│                    │
     │                    │  5. Token + ID     │
     │◀───────────────────│                    │
     │                    │                    │
     │  6. API-Anfrage    │                    │
     │────────────────────────────────────────▶│
     │                    │                    │
     │  7. FHIR-Daten     │                    │
     │◀────────────────────────────────────────│

SMART on FHIR App-Start

SMART-App-Start implementieren:

const crypto = require('crypto');

class SMARTClient {
  constructor(config) {
    this.clientId = config.clientId;
    this.redirectUri = config.redirectUri;
    this.issuer = config.issuer; // FHIR-Server-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 für den Token-Austausch speichern
    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
    };
  }
}

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

// Benutzer zur Auth-URL weiterleiten
const state = crypto.randomBytes(16).toString('hex');
const authUrl = smartClient.buildAuthUrl(state);
console.log(`Weiterleiten zu: ${authUrl}`);

Erforderliche SMART-Scopes

Scope Berechtigung Anwendungsfall
openid OIDC-Authentifizierung Für alle Apps erforderlich
profile Benutzerprofilinformationen Anbieterverzeichnis
patient/Patient.read Patientendemografie lesen Patientensuche
patient/Observation.read Beobachtungen lesen Vitalwerte, Labore
patient/Condition.read Bedingungen lesen Problemlisten
patient/MedicationRequest.read Medikationen lesen Medikationshistorie
patient/*.read Alle Patientenressourcen lesen Vollständige Patientendaten
user/*.read Alle zugänglichen Ressourcen lesen Anbieteransicht
offline_access Refresh Token Langlebige Sitzungen

Authentifizierte FHIR-Anfragen stellen

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-Fehler: ${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()}`);
  }
}

// Verwendung nach OAuth-Callback
const fhirClient = new FHIRClient(tokens.accessToken, 'https://fhir.epic.com');
const patient = await fhirClient.getPatient(tokens.patientId);

Batch- und Transaktionsoperationen

Batch-Anfragen

Mehrere unabhängige Anfragen ausführen:

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

// Verwendung - Mehrere Ressourcen abrufen
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(`Antwort ${index}: ${entry.response.status}`);
  console.log(entry.resource);
});

Transaktionsanfragen

Mehrere Anfragen als atomare Einheit ausführen:

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

// Verwendung - Patient und zugehörige Ressourcen erstellen
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' } // Referenz zur ersten Ressource
    }
  }
]);

Abonnements und Webhooks

FHIR-Abonnements (R4B+)

Ressourcenänderungen abonnieren:

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

// Verwendung - Neue Laborergebnisse abonnieren
const subscription = await createSubscription({
  criteria: 'DiagnosticReport?category=laboratory&patient=12345',
  reason: 'Laborergebnisse des Patienten überwachen',
  endpoint: 'https://myapp.com/webhooks/fhir'
});

FHIR-Webhooks behandeln

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

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

  // Abonnementreferenz überprüfen
  if (notification.subscription !== expectedSubscription) {
    return res.status(401).send('Nicht autorisiert');
  }

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

    // Neues Laborergebnis verarbeiten
    await processLabResult(report);
  }

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

Häufige Probleme beheben

Problem: 401 Nicht autorisiert

Symptome: Erhalten von "Nicht autorisiert" oder "Ungültiges Token"-Fehlern.

Lösungen:

  1. Überprüfen, ob das Token nicht abgelaufen ist
  2. Überprüfen, ob der Token-Scope die angeforderte Ressource enthält
  3. Sicherstellen, dass der Header Authorization: Bearer {token} vorhanden ist
  4. Überprüfen, ob die FHIR-Server-URL mit der Token-Zielgruppe übereinstimmt

Problem: 403 Verboten

Symptome: Token ist gültig, aber der Zugriff wird verweigert.

Lösungen:

  1. Überprüfen, ob der Benutzer die Berechtigung für die angeforderte Ressource hat
  2. Überprüfen, ob der Patientenkontxt übereinstimmt (für patientenbezogene Tokens)
  3. Sicherstellen, dass die SMART-Scopes die angeforderte Operation enthalten
  4. Zugriffskontrollen auf Ressourcenebene überprüfen

Problem: 404 Nicht gefunden

Symptome: Ressource existiert nicht oder der Endpunkt ist falsch.

Lösungen:

  1. Überprüfen, ob die Ressourcen-ID korrekt ist
  2. Überprüfen, ob die FHIR-Basis-URL korrekt ist
  3. Sicherstellen, dass der Ressourcentyp vom Server unterstützt wird
  4. Versionsspezifischen Endpunkt überprüfen (R4 vs R4B)

Problem: 422 Unverarbeitbare Entität

Symptome: Validierungsfehler beim Erstellen/Aktualisieren.

Lösungen:

// Validierungsfehler parsen
const error = await response.json();
error.issue?.forEach(issue => {
  console.log(`Schweregrad: ${issue.severity}`);
  console.log(`Ort: ${issue.expression?.join('.')}`);
  console.log(`Nachricht: ${issue.details?.text}`);
});

Häufige Ursachen:

Checkliste für die Produktionsbereitstellung

Vor der Liveschaltung:

FHIR-Validierung

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(`Validierungsfehler: ${issue.message}`);
      console.error(`Ort: ${issue.path}`);
    });
    throw new Error('Ressourcenvalidierung fehlgeschlagen');
  }

  return true;
};

// Verwendung vor dem Erstellen/Aktualisieren
await validateResource(patientResource);

Anwendungsfälle aus der Praxis

Integration des Patientenportals

Ein Gesundheitssystem baut ein Patientenportal auf:

Wichtige Implementierung:

Klinische Entscheidungsunterstützung

Eine Plattform für das Versorgungsmanagement fügt CDS hinzu:

Wichtige Implementierung:

Analysen zur Bevölkerungsgesundheit

Ein Kostenträger erstellt ein Dashboard zur Bevölkerungsgesundheit:

Wichtige Implementierung:

Fazit

HL7 FHIR bildet die Grundlage für die moderne Interoperabilität im Gesundheitswesen. Wichtige Erkenntnisse:

Schaltfläche

FAQ-Bereich

Wofür wird HL7 FHIR verwendet?

FHIR ermöglicht den standardisierten Austausch von Gesundheitsdaten zwischen EHRs, Patientenportalen, mobilen Apps und anderen Gesundheits-IT-Systemen. Häufige Anwendungsfälle sind Patientenzugriffs-Apps, klinische Entscheidungsunterstützung, Bevölkerungsgesundheit und Versorgungskoordination.

Wie fange ich mit FHIR an?

Beginnen Sie mit dem Zugriff auf einen öffentlichen FHIR-Server (wie den HAPI FHIR-Testserver) oder richten Sie einen Cloud-FHIR-Dienst ein (Azure API for FHIR, AWS HealthLake). Üben Sie das Lesen von Ressourcen und die Verwendung von Suchparametern.

Was ist der Unterschied zwischen HL7 v2 und FHIR?

HL7 v2 verwendet durch Pipe getrennte Nachrichten (ADT, ORM, ORU) für den ereignisgesteuerten Datenaustausch. FHIR verwendet RESTful APIs mit JSON/XML für den ressourcenbasierten Zugriff. FHIR ist einfacher zu implementieren und besser für moderne Web-/Mobile-Apps geeignet.

Ist FHIR HIPAA-konform?

FHIR selbst ist ein Datenformatstandard. Die HIPAA-Konformität hängt von der Implementierung ab: Verschlüsselung, Authentifizierung, Zugriffskontrollen und Audit-Protokollierung. Verwenden Sie OAuth 2.0 mit SMART on FHIR für sicheren Zugriff.

Was sind SMART-Scopes?

SMART-Scopes definieren granulare Zugriffsrechte für FHIR-Ressourcen (z.B. patient/Observation.read, user/*.read). Fordern Sie nur die Scopes an, die Ihre App benötigt.

Wie suche ich nach Ressourcen in FHIR?

Verwenden Sie GET-Anfragen mit Abfrageparametern: /Patient?name=Smith&birthdate=ge1980-01-01. FHIR unterstützt Modifikatoren (:exact, :contains) und Präfixe (gt, lt, ge, le).

Was ist Bulk FHIR?

Bulk FHIR ($export) ermöglicht den asynchronen Export großer Datensätze im NDJSON-Format. Es wird für Bevölkerungsgesundheit, Analysen und Data Warehousing verwendet.

Wie gehe ich mit FHIR-Versionierung um?

Zielen Sie auf eine bestimmte FHIR-Version (R4 empfohlen) und verwenden Sie versionsspezifische Endpunkte. Überprüfen Sie das CapabilityStatement auf unterstützte Versionen und Ressourcen.

Kann ich FHIR mit benutzerdefinierten Feldern erweitern?

Ja, verwenden Sie FHIR-Erweiterungen, um benutzerdefinierte Datenelemente hinzuzufügen. Definieren Sie Erweiterungen in Ihrem Implementation Guide und registrieren Sie sie bei HL7, wenn Sie sie breit teilen möchten.

Welche Tools helfen bei der FHIR-Entwicklung?

Beliebte Tools sind HAPI FHIR (Open-Source-Server), FHIR-Validator, Postman-Sammlungen und Apidog für API-Tests und -Dokumentation.

Praktizieren Sie API Design-First in Apidog

Entdecken Sie eine einfachere Möglichkeit, APIs zu erstellen und zu nutzen