Chuyển đến nội dung chính

Lesson 15: FHIR Subscriptions and Real-time Notifications

Topic-based Subscriptions (R5), SubscriptionTopic, Subscription resource, notification channels (rest-hook, websocket, email), notification types (handshake, heartbeat, event-notification), filters, payload content. Practice configuring Subscription on HAPI FHIR Server.

🏗️ Architecture — Lesson 15 Lesson 15: FHIR Subscriptions and Real-time Notifications

HL7 FHIR - Basic to Advanced Healthcare Data Standard

Part 5: Integration, Messaging and Security

xdev.asia

1. Subscriptions in FHIR R5

FHIR R5 introduced Topic-based Subscriptions — completely replaces the old mechanism of the R4. Allows the system to receive real-time notifications when data changes.


┌──────────┐      Subscribe       ┌──────────┐
│  Client  │ ──────────────────▶ │  FHIR    │
│  (EMR,   │                     │  Server  │
│  app)    │ ◀────────────────── │          │
│          │    Notification      │          │
└──────────┘                     └──────────┘

2. SubscriptionTopic

SubscriptionTopic definition "What can I subscribe to?" — events, triggers, filters available.

{
  "resourceType": "SubscriptionTopic",
  "id": "topic-encounter-admission",
  "url": "http://hospital.vn/fhir/SubscriptionTopic/encounter-admission",
  "title": "Encounter Admission",
  "status": "active",
  "description": "Thông báo khi có bệnh nhân nhập viện mới",
  "resourceTrigger": [
    {
      "description": "Encounter mới được tạo hoặc chuyển status sang in-progress",
      "resource": "http://hl7.org/fhir/StructureDefinition/Encounter",
      "supportedInteraction": ["create", "update"],
      "queryCriteria": {
        "current": "status=in-progress&class=http://terminology.hl7.org/CodeSystem/v3-ActCode|IMP",
        "resultForCreate": "test-passes",
        "resultForDelete": "test-fails"
      }
    }
  ],
  "canFilterBy": [
    {
      "description": "Filter theo location (khoa)",
      "resource": "Encounter",
      "filterParameter": "location"
    },
    {
      "description": "Filter theo service provider",
      "resource": "Encounter",
      "filterParameter": "service-provider"
    }
  ],
  "notificationShape": [
    {
      "resource": "Encounter",
      "include": [
        "Encounter:subject",
        "Encounter:participant"
      ]
    }
  ]
}

3. Subscription Resource

{
  "resourceType": "Subscription",
  "id": "sub-admission-notify-001",
  "status": "requested",
  "topic": "http://hospital.vn/fhir/SubscriptionTopic/encounter-admission",
  "reason": "Nhận thông báo nhập viện khoa Tim mạch",
  "filterBy": [
    {
      "resourceType": "Encounter",
      "filterParameter": "location",
      "value": "Location/loc-cardiology"
    }
  ],
  "channelType": {
    "system": "http://terminology.hl7.org/CodeSystem/subscription-channel-type",
    "code": "rest-hook"
  },
  "endpoint": "https://ehr-app.hospital.vn/api/webhooks/fhir-notifications",
  "heartbeatPeriod": 60,
  "timeout": 60,
  "contentType": "application/fhir+json",
  "content": "id-only",
  "maxCount": 10
}

Channel Types

ChannelDescriptionUse cases
rest-hookHTTP POST to the endpointServer-to-server integration
websocketWebSocket connectionReal-time UI, dashboards
emailEmail notificationsAlert for engineers
message. messageFHIR Messaging ($process-message)Integrated messaging systems

Content Levels

LevelDescription
emptyOnly notification header, no resource data
id-onlyResource ID + type, client fetches itself
full-resourcesContains all resources in the notification

4. Notification Types

Handshake Notification

Sent when the subscription is created, confirming the endpoint is active.

{
  "resourceType": "Bundle",
  "type": "subscription-notification",
  "entry": [
    {
      "resource": {
        "resourceType": "SubscriptionStatus",
        "type": "handshake",
        "subscription": {
          "reference": "Subscription/sub-admission-notify-001"
        },
        "topic": "http://hospital.vn/fhir/SubscriptionTopic/encounter-admission",
        "eventsSinceSubscriptionStart": "0"
      }
    }
  ]
}

Event Notification

{
  "resourceType": "Bundle",
  "type": "subscription-notification",
  "entry": [
    {
      "resource": {
        "resourceType": "SubscriptionStatus",
        "type": "event-notification",
        "subscription": {
          "reference": "Subscription/sub-admission-notify-001"
        },
        "topic": "http://hospital.vn/fhir/SubscriptionTopic/encounter-admission",
        "eventsSinceSubscriptionStart": "5",
        "notificationEvent": [
          {
            "eventNumber": "5",
            "focus": {
              "reference": "Encounter/enc-new-001"
            },
            "additionalContext": [
              {"reference": "Patient/patient-new-001"}
            ]
          }
        ]
      }
    },
    {
      "fullUrl": "https://fhir-server.example.com/fhir/r5/Encounter/enc-new-001",
      "resource": {
        "resourceType": "Encounter",
        "id": "enc-new-001",
        "status": "in-progress"
      }
    }
  ]
}

Heartbeat Notification

Send periodically to confirm subscription is active, even when there are no events.

5. Subscription Lifecycle


requested → active → error → off
    │          │        │
    │          │        └── Server tạm dừng sau nhiều lần gửi thất bại
    │          └── Nhận handshake thành công
    └── Client POST Subscription

6. Practice Subscriptions on HAPI FHIR

# 1. Kiểm tra SubscriptionTopics có sẵn
curl -s https://hapi.fhir.org/baseR5/SubscriptionTopic | jq '.entry[].resource.url'

# 2. Tạo Subscription
curl -X POST https://hapi.fhir.org/baseR5/Subscription \
  -H "Content-Type: application/fhir+json" \
  -d '{
    "resourceType": "Subscription",
    "status": "requested",
    "topic": "http://example.org/FHIR/SubscriptionTopic/admission",
    "channelType": {"code": "rest-hook"},
    "endpoint": "https://your-webhook.example.com/fhir-notify",
    "contentType": "application/fhir+json",
    "content": "id-only"
  }'

# 3. Kiểm tra status
curl -s https://hapi.fhir.org/baseR5/Subscription/sub-id | jq '.status'

# 4. Tạo Encounter để trigger notification
curl -X POST https://hapi.fhir.org/baseR5/Encounter \
  -H "Content-Type: application/fhir+json" \
  -d '{"resourceType":"Encounter","status":"in-progress","class":[{"coding":[{"code":"IMP"}]}],"subject":{"reference":"Patient/123"}}'

7. Summary

  • SubscriptionTopic — Server defines events that can be subscribed

  • Subscription — Client registers to receive notifications, selects channel, filter, content level

  • Channels — rest-hook (most common), websocket, email, message

  • Notification types — handshake, heartbeat, event-notification

  • Completely replaces the old Subscription mechanism of R4 (criteria-based)