Netherlands - Generic Functions for data exchange Implementation Guide
0.3.0 - ci-build
Netherlands - Generic Functions for data exchange Implementation Guide, published by Stichting Nuts. This guide is not an authorized publication; it is the continuous build for version 0.3.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/nuts-foundation/nl-generic-functions-ig/ and changes regularly. See the Directory of published versions
| Page standards status: Draft |
This page specifies how FHIR-based event notifications are exchanged between organizations in the Dutch healthcare ecosystem. It describes a generic transport layer that other Implementation Guides and use cases (e.g. Notified Pull) build upon: a sending organization signals to a receiving organization that something it cares about has happened, and the receiver pulls the current state from the sender's FHIR endpoint.
The framework is based on the FHIR Subscription Framework, implemented in FHIR R4 via the Subscriptions R5 Backport for R4. It uses three core resources: SubscriptionTopic (defining events and triggers), Subscription (describing the receiver's interest in notifications), and notification Bundles (carrying event-notification, handshake-notification or heartbeat-notification). Clients request notifications based on specific topics, and servers send them over a configured channel.
Key design principles include:
Here is a brief overview of the processes that are involved:
Subscription is registered for the receiving organization (the Subscription Client) against an agreed SubscriptionTopic. How this Subscription is created is use-case defined (in-band or out-of-band); see Subscription.handshake-notification to confirm the channel and updates Subscription.status accordingly.event-notification Bundle to the receiver, with a monotonically increasing event-number.heartbeat-notification so the receiver can detect channel outages.event-number, and uses the $event and $status operations on the sender to catch up or query state.The Subscription Server runs at the sending party and is responsible for managing subscriptions and delivering notifications. It MUST:
Subscription resources for the agreed (Out-of-band Managed) SubscriptionTopic(s).handshake-notification Bundles when Subscription.status is requested (with retries) and update Subscription.status accordingly;heartbeat-notification Bundles at predefined intervals (with retries) and update Subscription.status accordingly;event-notification Bundles, incrementing event-number in a concurrent-safe way;Subscription resource so clients can query state and catch up on missed events:
$status and $event operations;read and search interaction with search parameters status, criteria, channel.endpoint, channel.type and channel.payload;The Subscription Server MAY support creation of subscriptions by Subscription Clients (In-band Managed Subscriptions).
The Subscription Client runs at the receiving party and consumes notifications. It MUST:
event-number it has successfully processed. Missed notifications are caught up using the sender's $event operation;heartbeat-notification was missed. If so, the subscription status is queried using the sender's $status operation.The Subscription Client, being responsible for resolving failures, should also track the subscription's state to highlight and fix any erroneous communication.
A brief description of the data models used in this guide:
A Subscription is created at the sending organization for a receiving organization before any notifications flow. The pattern is a broad, long-lived Subscription per partner for a given use-case topic, not a Subscription per case. A single Subscription covers all events that match the topic and filter between the two partners.
How the Subscription is created is use-case defined: it MAY be created in-band (the client POSTs a Subscription to the server) or out-of-band.
For out-of-band managed subscriptions, the receiver's notification endpoint is typically resolved via the addressing function (Care Services Query Directory); see the endpoint discovery example. An Endpoint capable of receiving notifications is defined by connectionType = hl7-fhir-rest and .payloadType = Subscription (see Endpoint profile.
The server MUST check for an existing Subscription for the client before sending notifications; beyond that, the creation mechanism does not affect runtime behavior.
A Subscription SHALL:
Subscription.status = active while in use and off to retire the channel;SubscriptionTopic canonical URL on Subscription.criteria (using the Backport IG backport-topic-canonical extension where the criteria element cannot itself hold the canonical) and MAY carry a refining filter using backport-filter-criteria;Subscription.channel.type = rest-hook with the receiver's notification endpoint;Subscription.channel.payload = application/fhir+json and the Backport IG backport-payload-content extension to id-only.A Subscription example is in the IG artifacts: a long-lived Subscription at one organization that fires whenever a Task is owned by a partner organization identified by URA.
Each event matching the SubscriptionTopic and filter triggers one notification to the receiver. The notification is a FHIR Bundle of type history conforming to the Backport IG backport-subscription-notification profile. It contains a Parameters resource (SubscriptionStatus) conforming to backport-subscription-status-r4 with at minimum:
subscription — reference to the registered Subscription;status — active or off;type — event-notification, handshake-notification or heartbeat-notification;notification-event.event-number — monotonically increasing, used by the receiver to detect missed events;notification-event.timestamp — when the event occurred at the sender;notification-event.focus — reference to the resource the event is about (e.g. the Task on the sender).The notification carries no clinical content. With id-only payload the receiver learns only that a referenced resource has changed and pulls it from the sender's FHIR endpoint to obtain the current state.
A notification Bundle example and its SubscriptionStatus Parameters are in the IG artifacts; together they notify a partner that it is the proposed owner of a Task held at the sender.
A SubscriptionTopic defines the events that trigger notifications and the resource shape they apply to. SubscriptionTopics are owned and published per use case; each Implementation Guide that builds on this transport layer is responsible for defining (or referencing) the topics it uses, and for binding them to a canonical URL referenced by Subscription.criteria.
Notification endpoints MUST require mTLS. Authentication and authorization for notifications and for the subsequent pull on the sender's FHIR endpoint follows the GF Authorization specification.
Because notifications use id-only payload, the notification Bundle itself contains no clinical content and minimal personal data. The actual resource content is only disclosed when the receiver pulls it from the sender's FHIR endpoint, where the sender re-evaluates authorization at the moment of access.
A sending organization holds a Task that names a partner organization (identified by URA) as its (proposed) owner. A long-lived Subscription exists at the sender for that partner against a topic that fires when a Task's owner matches the partner's URA. When the Task is created, the Subscription Server sends an event-notification Bundle to the partner's notification endpoint; the partner reads the Task from the sender to learn what to do next.
The example artifacts for this scenario are the Subscription and the notification Bundle with its SubscriptionStatus Parameters.
Potential future enhancements include:
SubscriptionTopic canonical URLs;