Introduction
This Technical Agreement (TA) describes and specifies the technical responsibilities to which parties agree when connecting to exchange transactions to facilitate notifications.
Notifications support the information needs of receivers: they enable healthcare professionals, patients, or the systems they use to become aware of new data and changes in existing data as soon as these are registered.
This specification describes how Dutch healthcare organizations exchange such notifications in a consistent and secure manner, defining the functional principles and the technical choices required for interoperable, implementable notification exchange. As a technical foundation, we use the FHIR R5 Subscription Framework, applied in FHIR R4 via the Subscriptions R5 Backport Implementation Guide (IG).
This TA applies to FHIR R4 only. This version choice concerns only the subscription and notification framework itself; it does not require the resources referenced by notification-event.focus or notification-event.additional-context to conform to the same FHIR version.
FHIR R4B and R5. This TA is specified for FHIR R4. For reference, the main differences in later versions are as follows. Under FHIR R4B, the Backport IG uses the SubscriptionTopic resource for topic definitions, and a SubscriptionStatus resource instead of a Parameters resource as the first entry of the notification Bundle, with a separate Bundle profile (backport-subscription-notification). In FHIR R5, topic-based subscriptions are part of the core specification: Subscription.topic replaces the use of Subscription.criteria, and notifications use Bundle type subscription-notification. Adopting either version requires a new version of this TA; it is not an implementer option under this version.
The conformance verbs SHALL, SHALL NOT, SHOULD, SHOULD NOT and MAY in this document are to be interpreted as defined in FHIR R4 (Conformance Rules, Conformance Language), when, and only when, they appear in capitals.
Context
The initial reason for drawing up this generic technical agreement is the need for a FHIR specification for the exchange of the BgZ (Basisgegevensset Zorg, known in English as the Common Clinical Dataset) between healthcare organizations in the context of a referral. The BgZ is the Dutch patient summary: a standardized set of core patient data (e.g. problems, medication, allergies, procedures) intended to be exchangeable across care settings, comparable in purpose to the International Patient Summary. The actual agreements for the exchange of the BgZ are provided in the BgZ attachment. The exchange of the BgZ is not the only use case that requires a FHIR specification for the exchange of a set of FHIR resources between healthcare organizations in the context of a transfer of care. The eOverdracht information standard and corresponding TA cover a similar use case and already provide a specification for the exchange of FHIR resources using a Notified Pull pattern. As such, the relevant specifications in the eOverdracht information standard and TA have served as a basis for this document. At some points this document deviates from the eOverdracht information standard and TA (most specifically in the exchange of the notification). Where it deviates, it does not aim to replace the existing version of the eOverdracht standards and corresponding implementations. It rather aims to provide a direction for the next iteration of the eOverdracht information standard and TA.
The scope of this TA however is not limited to these use cases. It sets guidelines for the use and specification of notifications in other existing and future exchange agreements, including those required by EHDS.
Scope
In scope
-
The exchange of notifications between healthcare provider organisations, including the payload mode used (see Notification Payload Model).
-
The mechanism by which notification topics are scoped and narrowed (SubscriptionTopic, including trigger conditions and filter parameters).
-
The relationship with addressing (GF Addressing), authorization (GF Authorization), and the processing basis for exchange, including patient consent (GF Toestemming and, where applicable, EHDS), without defining a specific addressing profile.
Exclusions (out of scope)
-
Recall of a notification once sent. A notification cannot be withdrawn or cancelled after delivery; a notification relationship is ended by setting the Subscription's status to off (see Updating a Subscription).
-
Authentication and identification of the actors involved in the agreement (see TA I&A).
-
The retrieval of content that may follow a notification, where the notification itself does not carry that content, and any pattern that combines a notification with such a retrieval. This TA specifies only the notification (see TA Pull for the retrieval).
-
The technical method by which consent is verified (see GF Toestemming and forthcoming EHDS regulation).
-
The concrete registration, publication, and resolution of notification endpoints (see GF Addressing).
-
Notifications that do not concern patient-related healthcare data exchange. The technical notification framework described in this TA may be used for these kinds of notifications, but the patient-specific authorization, consent, privacy, and related governance requirements described herein do not apply.
-
Subscriptions at a FHIR base URL other than one registered under this TA (see Subscription Server), and the notifications sent for them. A Subscription Server or Subscription Client MAY take part in such exchanges, including for SubscriptionTopics not designated in a use-case-specific technical agreement. The requirements of this TA apply only to Subscriptions at the base URLs registered under this TA, and to the notifications sent for them.
-
The definition of specific SubscriptionTopics, including their coding and use-case binding, for a given exchange agreement or use case, and any routing information this makes available to the receiver (see the applicable use-case-specific technical agreement).
Vocabulary
This TA uses several terms that carry a specific, technical meaning in FHIR distinct from their everyday English meaning. This section defines the terms this TA is built on.
-
Subscription Server — the system, run by the sending organisation, that persists Subscriptions and sends notifications to Subscription Clients. See System Roles and Responsibilities for its full obligations.
-
Subscription Client — the system, run by the receiving organisation, that receives notifications at its notification endpoint and consumes them. See System Roles and Responsibilities for its full obligations.
-
zorgaanbieder — the healthcare provider organisation on whose behalf notifications are sent or received. Its identification and registration are governed by TA I&A and GF Addressing. This TA uses the Dutch term because it denotes this organisation as a party to the exchange, which is distinct from the party technically operating the systems involved (see GTK); "healthcare provider" could also be read as an individual healthcare professional.
-
GTK (Gekwalificeerd Twiin Knooppunt, qualified Twiin node) — a node qualified under the Twiin afsprakenstelsel through which a zorgaanbieder takes part in data exchange. A zorgaanbieder may operate its own GTK, or use a GTK offered by another party; a single GTK MAY act on behalf of multiple zorgaanbieders.
-
Notification — as used in this TA, a general term for the notification payload sent from the Subscription Server to the Subscription Client when an event occurs. A notification is not a FHIR Resource type. Mechanically, a notification is a FHIR Bundle of type
history, whose first entry is a Parameters resource carrying the subscription status information (backport-subscription-status-r4). See Resource Definitions. -
Subscription — a FHIR Resource that records the agreement between a Subscription Server and a Subscription Client about which notifications are delivered, for which SubscriptionTopic, and where. It is created either by the Subscription Client (in-band) or by the Subscription Server (out-of-band); see Creating a Subscription. Profiled for topic-based use in R4 by the Backport IG. Every notification SHALL be linked to an actual, registered Subscription resource; the Backport IG does not support sending notifications without one.
-
in-band, out-of-band — how a Subscription is created: in-band by the Subscription Client, through a create interaction at the Subscription Server; out-of-band by the Subscription Server itself, based on a prior agreement. See Creating a Subscription.
-
sender-initiated, receiver-initiated — which party initiates the notification relationship: the sending zorgaanbieder, or the receiving zorgaanbieder by requesting to be notified. Distinct from in-band and out-of-band: a sender-initiated relationship is typically set up out-of-band and a receiver-initiated one in-band, but requirements that depend on how a Subscription was created refer to in-band and out-of-band, not to the notification pattern. See Notification Patterns.
-
SubscriptionTopic — the definition of the class of event a Subscription can register for: which interactions on which resource type, under which further conditions, trigger it, and what a Subscription is allowed to filter on. In FHIR R4 there is no SubscriptionTopic resource; the Backport IG leaves topic definitions out of scope for R4. Under this TA, a topic is identified at runtime solely by its canonical URL. Its definition is designated in the applicable use-case-specific technical agreement, either as text in that agreement or as a published R4B or R5 SubscriptionTopic resource (see Resource Definitions → SubscriptionTopic).
-
notification-event.focus — the reference, carried in the notification-event part of the Parameters resource (
backport-subscription-status-r4) that forms the first entry of the notification Bundle, to the resource that triggered that specific event, which is a resource of the type the SubscriptionTopic monitors (see SubscriptionTopic). Present only in id-only and full-resource mode, absent in empty mode (see Notification Payload Model and Resource Definitions → Notification). -
canonical — a URL used as a stable, versionable identifier for a FHIR definitional resource (such as a SubscriptionTopic), as opposed to a literal reference, which points at a specific instance on a specific server.
-
id — as used in this TA, the logical id of a resource (
Resource.id), as carried in a literal reference such asnotification-event.focus. Distinct from identifier. -
identifier — an element of the FHIR Identifier datatype (
system+value) on a resource or a reference, such as Task.identifier or Reference.identifier. Not used in this TA to refer to Resource.id; see id. -
criteria — the
Subscription.criteriaelement, which under the Backport IG SHALL contain the canonical URL of the SubscriptionTopic the Subscription is bound to, not an R4 search expression. Scoping filters are carried separately, in one or morebackport-filter-criteriaextensions onSubscription.criteria, each in the filter syntax defined by the Backport IG ([filterParameter]=[value], optionally with a:[modifier]), using only filter parameters the topic definition allows (e.g.owner=http://fhir.nl/fhir/NamingSystem/ura|12104037). The[resourceType].prefix the Backport IG allows for disambiguation is not needed, since each topic monitors a single resource type.
Notification Payload Model
The payload mode determines what data travels inside the notification Bundle versus what must be retrieved later via a follow-up pull. Payload modes are requested per Subscription. The Subscription Server either accepts the requested mode or rejects the Subscription; it SHALL NOT accept a Subscription with a modified payload mode (see Payload Mode Agreement and Enforcement). The Backport IG permits a server to accept a Subscription with modifications; this TA excludes that for the payload mode. Existing exchange agreements (e.g., Referral or Transfer standards) may also pre-define or restrict which modes are permissible for specific SubscriptionTopics.
The payload modes, defined by the Backport IG (Backport IG payload modes) are:
|
Payload Mode |
|
Description |
|---|---|---|
|
Empty |
|
Contains no reference to the resource that triggered the event and no clinical data. The Bundle merely signals that a matching event occurred for the Subscription; the only reference it carries is to the Subscription itself. |
|
Id-only |
|
Contains a reference to the affected resource ( |
|
Full-resource |
|
Contains the complete FHIR resource instance itself. |
Authorization and Processing Basis for the Push Pattern
Full-resource mode has no separate retrieval step: there is no gap between notification and access. The notification is atomic: it carries the resource content itself, so sending it is the disclosure, not a precursor to one. The resource it carries may itself reference other resources that the receiver retrieves separately (see TA Pull), so a notified pull remains possible in full-resource mode.
Sending a notification does not exempt the sender from the authorization and processing-basis obligations that would otherwise apply to disclosing that same content – see Privacy, Consent, and Authorization for what full-resource mode specifically requires.
Payload Selection when the Receiver Retrieves Content Afterwards
This section addresses notifications after which the receiver retrieves the content separately — a Notified Pull–style exchange is a common example. The notification does not presuppose that the basis for that retrieval already exists; it may, or it may still need to be established. The payload is therefore limited to what is strictly necessary. The id-only and empty payload modes exist for exactly this kind of situation.
When choosing between them — full-resource mode is out of scope for this section, since sending it discloses the content directly rather than deferring access (see Authorization and Processing Basis for the Push Pattern) — id-only provides a literal reference to the affected resource to facilitate efficient retrieval, whereas empty conveys no identifying information.
Data exposed by an id-only notification
An id-only notification puts the resource reference in front of more parties than just the intended, authorized receiver. Three of them matter here:
-
The addressed but unauthorized recipient. The receiver of the notification itself may not yet have any right to the content — the notification arrives before access has been granted or established, so at that moment it only knows a resource exists and where.
-
The observer. Anything the notification passes through — message brokers, proxies, logs, backups — stores or forwards the reference too, typically for longer than the exchange itself lasts and to people who were never party to it.
-
Linked parties. Two or more parties who each separately receive ids legitimately can compare notes: an id that means nothing to either one alone can let them link the same resource across their separate views, something neither could do on their own.
If the id itself gives nothing away beyond its own recurrence, it adds nothing to what these three parties learn about the resource's content, order, timing, or real-world identity. A stable id necessarily still allows a party who sees it more than once to recognise that two notifications concern the same resource rather than two different ones; this minimal disclosure is inherent to the stability requirement itself (see Requirements for Using Id-Only) and cannot be eliminated without abandoning id-only mode altogether. But the sending organisation has no way to control this through access rules of its own: all three kinds of exposure happen in systems it doesn't operate (the receiver's inbox, the observer's logs, another party's records). The only lever it has is how the id is constructed before it is sent. That is why the conditions that follow are fixed requirements on every id leaving a source system, not something each implementer weighs case by case. The notification as a whole also discloses metadata regardless of payload mode: the event-number reveals how many events have occurred for the Subscription, the timestamp when each occurred, and the Subscription reference which Subscription they belong to (see Resource Definitions → Subscription). That metadata is inherent to the notification mechanism and is not addressed by requirements on the id.
Requirements for Using Id-Only
An id may be used as the reference in an id-only notification only if it satisfies the following requirements:
-
Stability — a source SHALL return the same id for the same resource on every request. Where the source uses per-recipient ids (see Appendix A), the id MAY differ between receivers, but SHALL remain the same for each individual receiver.
-
Opacity — a resource id SHALL NOT reveal creation order, volume, creation time, or content.
-
Unpredictability — a resource id SHALL NOT be guessable, and SHALL NOT be computable or confirmable from real-world identifying numbers (a BSN, a patient number) by anyone who does not hold a secret of the source. To be not guessable, an id SHALL carry at least 64 bits of entropy: either generated by a cryptographically secure random number generator, or produced by a keyed transformation with a secret key and an output of at least 64 bits. Only the random or keyed part of an id counts towards this minimum. The minimum follows the OWASP Session Management Cheat Sheet, which sets it for session identifiers. It applies to ids under this TA as well, although these stay valid indefinitely: guessing an id takes a request to the Subscription Server per attempt, and succeeds only where access control also fails.
-
Consumer opacity — a consumer SHALL treat received ids as opaque strings: it SHALL NOT parse them, derive meaning from them, or assume a format when querying, however carefully the id was constructed on the sending side.
An id that fails the opacity or unpredictability requirement leaks something about the resource to anyone who merely sees the notification, whether or not that party is ever granted access to the resource itself — which is exactly what disqualifies it from id-only use.
See Appendix A: Id Construction - Illustrative Examples for constructions that satisfy or fail these requirements.
When a Reference Is Preferable to Empty
For a single-receiver resource whose id meets the requirements above, id-only SHOULD be used in preference to empty — that is the central rule this section argues for; broadly accessible resources are the exception, addressed at the end of this section.
Some resources are addressed to a single receiver: a Task assigned to one care organisation, for example, where exactly one authorized party ever receives a notification about that resource. Others are broadly accessible: an Observation or a Patient record may be shared with many parties over time, each receiving their own notification referencing the same resource. What follows argues the rule above for the single-receiver case.
A receiver fetches a resource from its source using the id that names it. When the notification carries that id, the receiver knows exactly which resource is meant and can fetch it directly, without searching for a candidate match.
Choosing empty to avoid disclosure through the id does not avoid disclosure to the intended recipient — it moves it elsewhere, to the search response. It does, however, avoid disclosure to the observer and to linked parties (see Data exposed by an id-only notification), since no id is sent for them to see, log, or compare in the first place. Without a reference, the receiver must locate the resource by searching instead of fetching it directly, and a search response can contain more resources than the one the notification actually concerned. A reference that meets the opacity and unpredictability requirements, retrieved by direct read, discloses exactly one resource and nothing else; a search, by contrast, can expose a broader set of resources than the notification ever intended to point to. This is a matter of data minimisation, not of access control: a search returns only resources the receiver is authorized to access, but within that authorization, more than the event concerned. How much more depends on how narrowly the receiver's authorization is scoped. Where authorization is limited to the resource an event concerns, the difference between direct read and search largely disappears, and the case for id-only rests mainly on efficient retrieval.
For single-receiver resources whose id meets the requirements above, the notification’s reference SHOULD be sent, as an absolute URL in notification-event.focus, rather than withheld. Empty remains the right choice only where the id cannot meet the requirements above in the first place.
For broadly accessible resources, meeting the requirements is not sufficient on its own: the same reference value reaches every recipient, which gives linked parties material to cross-reference across their separate views of the same resource — something a single-receiver notification does not expose. Whether id-only remains appropriate for such resources, or whether per-recipient ids or empty mode should be used instead, is a decision for the use-case-specific technical agreement governing that exchange (see Requirements on Use-Case-Specific Technical Agreements), not a default this document can set.
Empty Mode with a Leaked Id Is Pseudo Id-Only
The empty mode's distinguishing security property is precisely that it carries no reference to the resource concerned. If an implementer nonetheless exposes the resource id through another channel available to the receiver (for instance in a header or a token accompanying the notification), the payload mode is still labeled empty even though the receiver in practice obtains the id. Notifications built this way no longer deliver the protection the empty mode is meant to provide; functionally, they are pseudo id-only notifications: they carry the same disclosure id-only mode would, without being declared or governed as id-only under the agreed payload mode. This holds regardless of whether the leaked id itself would satisfy the requirements in Requirements for Using Id-Only, the defect lies in the undeclared, ungoverned channel, not necessarily in the id's construction.
Payload Mode Agreement and Enforcement
The permitted payload modes are defined per topic in the applicable use-case-specific technical agreement before a Subscription is created (see Requirements on Use-Case-Specific Technical Agreements); a single topic MAY permit more than one. Systems SHALL NOT accept a Subscription for a SubscriptionTopic or payload mode that is not designated in the applicable use-case-specific technical agreement (see Preconditions); this does not require pre-agreement of scoping filter values (backport-filter-criteria), which MAY be set freely within the bounds of the filter parameters the SubscriptionTopic definition allows.
The payload mode is fixed when a Subscription is created and SHALL NOT be changed on an existing Subscription. Each payload mode requires its own processing basis and authorization (see Privacy, Consent, and Authorization), so a change of mode is a new activation: it requires a new Subscription, subject to the checks and handshake that apply to any new Subscription (see Replacing a Subscription). Every notification SHALL adhere to the payload mode registered on its Subscription. If the governing exchange agreement no longer permits the payload mode of an existing Subscription, that Subscription SHALL be set to off and, where notifications are still required, replaced. How the mode gets set depends on who creates the Subscription:
-
In-band creation (FHIR: In-Band Managed Subscription). The receiver creates the Subscription resource and SHALL specify the payload mode via the
backport-payload-contentextension onchannel.payload, which the Backport IG requires. The receiver SHALL only specify a mode pre-approved in the exchange agreement, and the sender is bound to that mode once it accepts. Senders SHALL NOT accept subscriptions requesting a mode outside the agreement. -
Out-of-band creation (FHIR: Out-of-Band Managed Subscription). The sender creates the Subscription resource and specifies the payload mode in the
backport-payload-contentextension, then sends a handshake notification to verify the channel is reachable. Agreement on the payload mode is established beforehand, via the governing exchange agreement, not via the handshake. A handshake carries no clinical content regardless of the agreed payload mode, so successfully processing one demonstrates reachability and correct Bundle handling, not that the receiver has verified the specific payload mode set on the Subscription. The receiver MAY inspect the payload mode by fetching the Subscription resource to confirm it matches the exchange agreement, but this is a separate check, not part of the handshake. If the requested mode falls outside the exchange agreement, the receiver SHALL reject the handshake, or refuse to acknowledge it. The same applies if the SubscriptionTopic carried in the handshake (topic) is not one the receiver has agreed to receive. Even after a successful handshake, the receiver retains the right to reject any later notification that deviates from the agreed payload mode. -
The notification format (JSON or XML) is carried on channel.payload. Unlike the payload mode, it MAY be changed on an existing Subscription, provided the new format is one the Subscription Client supports: by the Subscription Client through Updating a Subscription, for in-band and out-of-band Subscriptions alike, and by the Subscription Server for out-of-band Subscriptions it created (see Resource Definitions → Subscription). Every notification sent afterward SHALL conform to the registered format.
Notification Patterns
Sender and receiver initiation are independent of payload mode; the distinction below applies to notifications generally, not only to those following the Notified Pull pattern.
Sender-Initiated Notifications
In a sender-initiated notification pattern, the sending healthcare provider initiates the Subscription for a receiving provider, under a SubscriptionTopic the receiving provider has agreed to receive through the applicable use-case-specific technical agreement. The receiving provider does not request the individual notification relationship, but the topic itself is never something the sender can impose unilaterally. The sending organisation establishes and manages the notification relationship and sends notifications when relevant events occur.
Examples include referral or transfer updates and a specialist making a new consultation report available in the patient's record.
Receiver-Initiated Notifications
In a receiver-initiated notification pattern, the receiving healthcare provider explicitly requests to be informed when specific events occur. The receiving organisation initiates the notification relationship and the sending organisation delivers notifications when relevant events occur.
Examples include laboratory result notifications and notification of changes to specific patient information.
Quality and Privacy Considerations
Signal Fatigue and Specificity
A notification is an external trigger that can disrupt the receiver's ongoing work, so how it is scoped and delivered matters. The immediate receiver of a notification is the Subscription Client — a system, not a person — which may in turn direct it to a human, such as a healthcare professional's worklist or inbox. Signal fatigue can occur at either point: a system flooded with low-value notifications burns processing capacity and complicates prioritization, and a person flooded with low-value notifications starts to ignore them altogether, including the ones that matter. Too few notifications carries the opposite risk and can harm patient care. A SubscriptionTopic SHOULD therefore be scoped narrowly enough that the notifications it produces are relevant to the process they concern, and where a topic definition allows further narrowing through filter parameters, a Subscription SHOULD use backport-filter-criteria to apply it (see SubscriptionTopic and Subscription) rather than relying on topic-level scoping alone.
Great care SHOULD therefore be given to the specificity of notifications.
Privacy, Consent, and Authorization
Processing basis and authorization address different aspects of deciding whether data may be exchanged and are established through different mechanisms. The processing basis is the legal ground under GDPR and, where applicable, EHDS that permits the data to be exchanged for a given purpose. This may, depending on the case, be the patient's consent, but another processing basis may also apply; this TA does not presume consent is the applicable basis in every case. Authorization determines whether all applicable conditions for exchanging data are satisfied, including both the applicable processing basis (where required) and whether a specific receiving party is entitled to receive notifications for a given SubscriptionTopic and a specific patient. This TA delegates these determinations to GF Authorization and GF Toestemming (and, where applicable, EHDS) rather than defining them. A notification SHALL NOT be sent unless all applicable authorization and processing-basis conditions are satisfied at the time it is sent.
All payload modes require the applicable processing basis and authorization to have been established, but coverage depends on content (see Notification Payload Model):
-
Empty / id-only notifications carry no resource content, but are not privacy-neutral: the fact that a resource of a given type changed, tied to a specific patient (via the Subscription) and that care relationships exist between patient and sender and patient and receiver, is itself a thin disclosure about that patient's record. This is the baseline privacy footprint of any notification under this TA. The applicable processing basis and authorization are verified per notification, before it is sent, for the patient that notification concerns (see Implementation Obligations). Creating or activating a Subscription discloses no patient data to the receiver and therefore requires no patient-specific verification. For in-band creation, the Subscription Server's response to the Subscription Client is itself an external disclosure, so the Client's authorization for the SubscriptionTopic is verified before the Subscription is accepted (see Preconditions).
-
Full-resource notifications carry the complete resource instance, and therefore its content. Depending on the resource type the topic monitors, this may be clinical content, other personal data, or data that is not personal data at all. Where the content includes personal data, it is subject to the same processing-basis and authorization requirements as any other disclosure of that content, equivalent to a Push of the data itself.
The exchange agreement selecting full-resource for a topic SHALL state what data the monitored resource contains (see Requirements on Use-Case-Specific Technical Agreements). Where that includes personal data, the applicable processing basis SHALL cover disclosure of that content to the receiver, not merely disclosure of the fact that it exists, and SHALL already be in place at the moment a notification is sent (not deferred to a later point), since full-resource mode has no separate content-access step to defer it to. Where the agreement establishes that the resource contains no personal data, these content-specific requirements do not apply to that topic; the requirements that apply to empty and id-only notifications still do, since the Subscription can tie a notification to a patient. This determination is made in the agreement and is not left to the implementer.
Where an event by design concerns no identified patient (see Resource Definitions → SubscriptionTopic), the patient-specific verification does not apply to that event; verification of the receiver's authorization for the SubscriptionTopic still does. This does not make such a notification privacy-neutral. Whether the data it concerns is in fact non-identifying, and on what basis it may be disclosed, is established in the use-case-specific technical agreement, not assumed by this TA.
In all cases, the Subscription Server SHALL verify authorization and the applicable processing basis before a notification is sent (see Implementation Obligations).
Preconditions
This TA sets the following rules for the use of notifications and Subscriptions:
-
All notifications and subscriptions (in-band and out-of-band) that are accepted SHALL be bound to a SubscriptionTopic designated in the applicable use-case-specific technical agreement (binding to a topic canonical is required by the Backport IG; the requirement that the topic is designated beforehand in a use-case-specific technical agreement is added by this TA). A bilateral arrangement between a Subscription Server and a Subscription Client does not suffice, since the requirements that apply to a topic, such as its permitted payload modes, patient resolution and processing basis, are set in that agreement. A Subscription whose SubscriptionTopic is no longer designated in the applicable use-case-specific technical agreement SHALL be set to off by the Subscription Server and, where notifications are still required, replaced (see Replacing a Subscription).
-
For in-band creation, the Subscription Server SHALL verify via GF Authorization, before accepting a Subscription, that the Subscription Client is authorized for the SubscriptionTopic. All processing-basis and authorization requirements for a notification (processing basis per GF Toestemming and, where applicable, EHDS; authorization via GF Authorization) SHALL be satisfied before that notification is sent (see Privacy, Consent, and Authorization).
-
All endpoints SHALL adhere to Network level security standards. Mutual TLS SHALL be applied.
-
For in-band creation, the Subscription Server SHALL verify, before accepting a Subscription, that the Subscription Client's channel.endpoint begins with the address of an Endpoint of the receiving zorgaanbieder in GF Addressing with payloadType
Notification(see Sequence Diagram, step 1). The comparison is made per path segment: channel.endpoint is either equal to that address, or that address followed by one or more further path segments. For example,https://receiver.example.org/notify/sub-17matches the addresshttps://receiver.example.org/notify, andhttps://receiver.example.org/notify-xdoes not. A Subscription Client can thus use a specific endpoint per Subscription without registering it in GF Addressing, while the endpoint remains bound to the receiving zorgaanbieder. That binding is the purpose of this verification: without it, a Subscription could direct notifications to any address, and mTLS alone does not establish that an address belongs to the receiving zorgaanbieder, since the certificate of a GTK identifies the GTK. Whether, and when, this is verified again during the lifetime of the Subscription is not prescribed by this TA. -
The Subscription Client SHALL verify, at the application layer, that each received notification originates from a zorgaanbieder for which the base URL of the relevant Subscription is registered in GF Addressing at the time the notification is received, independent of mTLS-layer authentication of the delivering GTK (see Subscription Client).
Authorization for Pulls under Out-of-Band Subscriptions
For out-of-band Subscriptions, an event-notification may carry an authorization value for the subsequent pull (see Resource Definitions → Notification). This depends on how the Subscription was created, not on which party initiated the notification relationship (see Notification Patterns). Whether and how a pull may rely on the prior notification, and whether authorization and the processing basis are reassessed at the moment of access, are governed by GF Authorization and TA Pull, not by this TA. For in-band Subscriptions, no authorization value is carried.
FHIR Technical Specification
Conformance
Implementations SHALL conform to the HL7® FHIR® Subscriptions R5 Backport Implementation Guide, version 1.1.0 (STU 1.1), using its FHIR R4 package (hl7.fhir.uv.subscriptions-backport.r4). This TA repeats selected implementer obligations from that guide so that the required behavior can be understood without a detailed study of the Backport specification.
Sequence Diagram
The diagram below illustrates the technical flow of the notification mechanism this TA specifies between the Subscription Client (receiving organisation) and the Subscription Server (sending organisation): subscription registration, handshake, recurring event/heartbeat notifications, catch-up after a disruption, and retirement of the Subscription. This mechanism can be used, for example, as the notification component of a Notified Pull–style exchange. The actual content retrieval (the pull itself) is out of scope of this TA (see TA Pull).
Not every step and operation is required by the Backport IG. Those that are optional are indicated below.
-
Subscription registration. On the sending organisation's side, a Subscription is created for the receiving organisation, bound to a pre-agreed SubscriptionTopic. The agreement on the topic rests with both parties: in the receiver-initiated pattern, the receiver requests to be notified; in the sender-initiated pattern, the sender initiates the Subscription under a topic the receiver has agreed to (see Notification Patterns). How the Subscription is technically established can be determined per use case:
-
in-band: POSTed by the Subscription Client to the Subscription Server's FHIR endpoint, known beforehand or resolved via GF Addressing as an Endpoint of the sending zorgaanbieder with connectionType
hl7-fhir-rest, payloadTypeSubscriptionand a payloadMimeType withfhirVersion=4.0. That base URL determines the zorgaanbieders whose events the Subscription concerns: every zorgaanbieder for which it is registered (see Resource Definitions → Subscription). The SubscriptionTopics a Subscription Server supports are discoverable via itsCapabilityStatement(see Subscription Server). -
out-of-band: set up by the Subscription Server based on a previously made agreement. For out-of-band subscriptions, the Subscription Client's notification endpoint, if not already known, can be looked up via GF Addressing as an Endpoint of the receiving zorgaanbieder with connectionType
hl7-fhir-rest, payloadTypeNotificationand a payloadMimeType withfhirVersion=4.0.
The payloadType codes Subscription and Notification are defined in the GF Addressing code system http://fhir.generiekefuncties.nl/csd/CodeSystem/nl-gf-data-categories-cs (GF Care Service Directory IG 1.0.0). Which Endpoints a zorgaanbieder uses follows from the references to them in GF Addressing: from Organization.endpoint of the Organization representing the zorgaanbieder or of an Organization that is part of it (directly or indirectly, through Organization.partOf), and from HealthcareService.endpoint of a HealthcareService provided by one of these Organizations (HealthcareService.providedBy). Endpoint.managingOrganization identifies the party managing the Endpoint, not the zorgaanbieder using it. Endpoint selection, taking Endpoint.status and Endpoint.period into account, follows GF Addressing. Where a later version of GF Addressing changes these codes, this TA follows that version.
Out-of-band Subscription creation is typically associated with the sender-initiated notification pattern, while in-band Subscription creation is typically associated with the receiver-initiated notification pattern. These concepts are related but distinct: the notification pattern describes which party initiates the notification relationship, whereas in-band and out-of-band describe the technical mechanism used to establish the Subscription. -
-
Handshake Immediately after registration, the Subscription Server SHALL send a handshake to the Subscription Client's notification endpoint to confirm the channel; only a successful handshake sets
Subscription.statustoactive.For the rest-hook channel type, a handshake is mandatory: per the Backport IG, the Subscription Server SHALL set the initial
Subscription.statustorequestedand SHALL update it toactiveonly after a successful handshake has been sent and accepted; any error in the handshake SHALL result in status being set toerror. -
Event notifications. Whenever an event occurs on the Subscription Server's side that matches the topic (and any applicable filter), the Subscription Server sends an event-notification Bundle. Each notification receives an event-number that increases by one for each event notified, so that the Subscription Client can detect missed notifications (see Resource Definitions → Notification). Unless the payload mode is
empty, the notification carries a focus reference (literal reference) to the source resource at the Subscription Server; it carries the resource content only if the payload mode isfull-resource(see Notification Payload Model). -
Heartbeats (if used). At pre-agreed intervals, the Subscription Server sends a heartbeat so that the Subscription Client can detect a channel outage, even when no events are actually occurring (see Heartbeat Notification for whether this applies to a given Subscription).
-
Catch-up after disruption. When the Subscription Client detects a gap in the event-number sequence, it queries
$statusto verify the Subscription status and, where the Subscription Server supports it, uses$eventsto retrieve the missed notifications. When it detects a missing expected heartbeat, it queries$status. The obligations for each case are set out under Subscription Client.The
$statusoperation informs the Subscription Client of the state of the subscription. The Subscription Server SHALL support this operation.The
$eventsoperation asks the server to replay past notifications. Subscription Servers MAY support this operation; support is not required. -
Follow up on notification The receiver can subsequently retrieve the content behind the focus reference via the sender's FHIR endpoint. The content pull and associated access control fall outside this specification (see GF's Identification, Authentication, Authorisation, Consent and the TA Pull).
-
Subscription retirement. A Subscription is ended by setting its status to off, not by deleting it. Either party MAY retire a Subscription, whichever party created it: the Subscription Server directly, the Subscription Client through Updating a Subscription. The Subscription Server also sets the status to off when delivery retries are exhausted, or when the applicable use-case-specific technical agreement no longer designates the Subscription’s SubscriptionTopic or permits its payload mode (see Preconditions and Payload Mode Agreement and Enforcement). This TA defines no notification of retirement; the Subscription Client detects that the Subscription Server has set a Subscription to off through a missed heartbeat or through $status (see Subscription Client).
$status, and$eventswhere supported, remain available on a Subscription set to off for the retention period agreed for replayable events (see Implementation Obligations).
System Roles and Responsibilities
Subscription Server
The Subscription Server runs on the sending organisation's side and is responsible for managing Subscriptions and delivering notifications. Its conformance baseline is the Backport IG's Subscription Server CapabilityStatement, with a few extra requirements.
Required by the Backport IG:
-
Support the
$statusoperation on the Subscription. -
Support
readon Subscription. -
Send a
handshakeand transitionSubscription.statusfromrequestedtoactive(orerror) for therest-hookchannel type. -
Optional support of
$events. -
Optional support of heartbeat; see Heartbeat Notification for how this TA layers on top of it.
Beyond the Backport IG, this TA specifies that the Subscription Server SHALL:
-
Create Subscription resources only for pre-agreed SubscriptionTopics (the topic-binding mechanism itself is the IG's; requiring prior mutual agreement on which topics are valid is added by this TA — see Preconditions);
-
Assign
event-numberin a concurrency-safe manner — the IG does not address concurrent assignment; -
Verify, before sending each notification, that a valid Subscription exists for the receiver, and that authorization and the applicable processing basis are still valid for that notification (see Implementation Obligations for the full timing rules — this verification obligation is a TA addition, not an IG requirement);
-
Where the applicable use-case-specific technical agreement specifies in-band creation for a given SubscriptionTopic, support Subscription creation by Subscription Clients for that topic, accepting only pre-agreed topics from entitled Clients — support for in-band creation is conditional on the use-case agreement, not a blanket capability;
-
Support the Updating a Subscription transaction, for in-band and out-of-band Subscriptions alike, accepting only the changes that transaction permits. The FHIR update interaction itself is not restricted by the Backport IG; the restriction is a TA addition.
-
Register, for each zorgaanbieder it acts for, a FHIR base URL in GF Addressing as an Endpoint of that zorgaanbieder, with connectionType
hl7-fhir-restand payloadTypeSubscription, also where it only creates Subscriptions out-of-band, so that Subscription Clients can verify the subscription reference in notifications (see Resource Definitions → Notification). A base URL MAY be registered for several zorgaanbieders; a Subscription at that base URL then concerns events of each of them (see Resource Definitions → Subscription). Every Subscription at that base URL is subject to this TA; Subscriptions outside this TA are offered at another base URL (see Scope). That other base URL MAY share its host with the base URL registered under this TA and differ from it only in path, and both MAY be served by the same system, monitoring the same data; this TA requires no separate environment or dataset. Each Subscription is, however, accessible only at the base URL at which it was created or, for out-of-band creation, registered: read, search, update and the $status and $events operations at a base URL registered under this TA return or affect only Subscriptions subject to this TA. -
Retry failed handshake and notification delivery with exponential backoff specifically — the IG only requires retry as such, without specifying a strategy (see Implementation Obligations);
-
Support both
application/fhir+jsonandapplication/fhir+xmlfor every transaction under this TA — FHIR R4 does not require a server to support both formats; this TA does, in line with the MedMij FHIR Implementation Guide (V2020.01, section 5.1 Content Types and encodings), which sets the same requirement for servers. Since a Subscription Client needs to support only one of the two formats, this ensures that every Subscription Server can serve every Subscription Client; -
Support
searchon Subscription with the parametersstatus,criteria,type,payload(FHIR R4) andpayload-type, in addition tourl; the Backport IG requiressearchonurl, and recommendssearchonstatus.
The Subscription Server SHOULD:
-
Where it supports in-band Subscription creation, advertise the SubscriptionTopics it supports in its
CapabilityStatement, using thecapabilitystatement-subscriptiontopic-canonicalextension defined by the Backport IG, so that Subscription Clients can discover them.
Subscription Client
The Subscription Client runs on the receiving organisation's side and consumes notifications. The Backport IG does not define a separate conformance statement for this role. The Subscription Client SHALL:
-
Receive notification Bundles at the notification endpoint and forward them internally to the processing system;
-
Accept handshake notification Bundles at the notification endpoint, since
Subscription.statuscannot become active until this succeeds (see Handshake Notification); -
Check every incoming Bundle for continuity, using the highest processed event-number. Upon detecting a gap, at minimum: (a) log the gap (see Implementation Obligations), and (b) query $status to confirm the Subscription's current state (active, off, or error). Where $events is supported, missed notifications SHOULD additionally be retrieved through it (see $status and $events Operations). Where $events is not supported, or does not cover the missed range, further reconciliation of the missed content follows the route stated in the applicable use-case-specific technical agreement (see Requirements on Use-Case-Specific Technical Agreements).
-
Verify, upon receiving a notification, that it originates from a zorgaanbieder for which the base URL of the relevant Subscription is registered in GF Addressing at that time (see Subscription Server), not merely from a GTK authenticated at the mTLS layer, since a single GTK MAY act on behalf of multiple zorgaanbieders. The notification Bundle itself carries no identity of the sending zorgaanbieder: the sending zorgaanbieder is taken from the authentication context of the notification request, as established per TA I&A and GF Authorization, and cross-checked at the application layer against the zorgaanbieders for which that base URL is registered. This TA does not define the authentication context itself.
-
Support at least one of
application/fhir+jsonorapplication/fhir+xml. The format used for the notifications of a given Subscription is the one set in that Subscription'schannel.payload.
The Subscription Client SHOULD:
-
Where heartbeats are used for a Subscription, check at the agreed interval whether a heartbeat notification has been missed, and compare its events-since-subscription-start with the highest processed event-number. On a missed heartbeat or a discrepancy, query $status and treat the discrepancy as a gap (see the gap-handling requirement above).
The Subscription Client MAY:
-
Create Subscription resources on its own initiative for the agreed SubscriptionTopic(s) at a Subscription Server.
-
Retire, or change the notification format of, any Subscription of which it receives the notifications, created in-band or out-of-band, through Updating a Subscription.
The Subscription Client is responsible for signalling and recovering from faulty communication, and SHOULD therefore keep track of the state of its Subscriptions.
Implementation Obligations
-
Logging. Both parties SHALL log the sending and receipt of Subscriptions and notifications (including handshake, and heartbeat where used) with enough detail to reconstruct, after the fact, which notifications were sent, received, or missed for a given Subscription. This is not addressed by the Backport IG, and is required by this TA to support incident investigation and to substantiate that the authorization and processing-basis verifications below were actually performed at the time a notification was sent, not only that a rule requiring them exists. This requirement concerns the notification channel itself, not access to patient record content; where applicable, logging of actual content access remains separately governed by NEN 7513.
-
Authorization verification. The Subscription Server SHALL verify, immediately before sending each notification, including each retry of it and each replay through
$events, that the receiver is authorized (via GF Authorization) to receive that notification. This covers at least the zorgaanbieder whose data that notification concerns, the SubscriptionTopic and, unless the event by design concerns no identified patient, the patient that notification concerns, as well as any further conditions on which GF Authorization makes the authorization depend. The Subscription Server SHALL also verify that the base URL of the Subscription is registered in GF Addressing for that zorgaanbieder at that time (see Resource Definitions → Subscription). For in-band creation, it SHALL in addition verify, before accepting the Subscription, that the Subscription Client is authorized for the SubscriptionTopic. This is independent of, and in addition to, the processing-basis verification below. Authorization can be withdrawn or expire on its own timeline, separate from the processing basis. -
Processing-basis verification. The Subscription Server SHALL verify, immediately before sending each notification, including each retry of it and each replay through
$events, that the processing basis applicable to that payload mode (see Privacy, Consent, and Authorization) still applies for the patient that notification concerns. Where the basis is consent, it MAY be withdrawn after a Subscription is created; the server is responsible for reflecting that at the time a notification is sent. -
Error reporting. All transactions SHALL return a FHIR OperationOutcome with an appropriate HTTP status code in case of errors (neither FHIR R4 nor the Backport IG mandates an OperationOutcome on every error path; this is required by this TA).
-
Retry. The sending party of a transaction (for notifications the Subscription Server, for Subscription creation and update and the
$statusand$eventsoperations the Subscription Client) SHALL retry transient errors (5xx, network errors, and 429 Too Many Requests) with exponential backoff. Other 4xx responses indicate a permanent error (e.g. malformed request, failed validation) and SHALL NOT be retried (the Backport IG only permits retry without specifying a strategy; this TA requires exponential backoff specifically). Where a 429 response carries a Retry-After header, the sending party SHALL NOT retry before the indicated time. For notifications, retries are exhausted when the maximum retry duration set by the use-case-specific technical agreement has elapsed (see Delivery failure and Subscription status). As an illustration only: each interval 1.5 times the previous, capped at 12 hours. -
Delivery failure and Subscription status. While the Subscription Server is retrying a failed event-notification or heartbeat, it SHALL set the Subscription's status to error, and SHALL set it back to active upon the next successful delivery. When retries are exhausted, it SHALL set the status to off; a Subscription set to off is not reactivated, and where notifications are still required, a new Subscription is created (see Replacing a Subscription). A notification rejected with a permanent error (4xx other than 429) is not retried, keeps its event-number, and sets the status to error. The Subscription Server SHALL continue to support $status, and $events where supported, on a Subscription set to off for the retention period agreed for replayable events. The same applies to the handshake, where the Backport IG requires any handshake error to set the status to error. A handshake rejected with a permanent error is not retried and the status is then set to off, since a Subscription that was never activated has no later delivery from which to recover.
-
Idempotency. Processing SHALL be idempotent: re-delivering a previously processed notification SHALL NOT cause duplicate side effects. This includes notifications for the same event under a replaced and a replacement Subscription (see Replacing a Subscription). Not addressed by the Backport IG; required by this TA.
Resource Definitions
Notification
A notification is a FHIR Bundle of type history, conforming to the Backport profile backport-subscription-notification-r4. The first entry SHALL be a Parameters resource conforming to backport-subscription-status-r4, with at least:
-
subscription— reference to the registered Subscription; SHALL be an absolute URL, resolvable by the Subscription Client without prior knowledge of the Subscription Server's base URL — consistent with hownotification-event.focusis recommended to be sent (see When a Reference Is Preferable to Empty). The Subscription Client SHALL verify that the base URL of this reference belongs to the sending zorgaanbieder, and SHALL NOT dereference a reference that does not match. For in-band Subscriptions, this is the base URL to which the Client submitted the Subscription; for out-of-band Subscriptions, the address of an Endpoint of that zorgaanbieder in GF Addressing with payloadType Subscription (see Sequence Diagram, step 1). -
status— the current status of the Subscription (requested, active, error, or off); a handshake is typically sent while the status is still requested;
-
type—handshake,heartbeat, orevent-notificationin notifications the Subscription Server sends;query-statusandquery-eventoccur only in responses to the$statusand$eventsoperations (see $status and $events Operations ). -
topic — the canonical URL of the SubscriptionTopic, identical to Subscription.criteria. Required by this TA in every notification, so that the Subscription Client can verify the topic of an out-of-band Subscription upon receiving its handshake (see Payload Mode Agreement and Enforcement).
Every entry in the Bundle SHALL carry a request element and a response element, as required for history Bundles (invariants bdl-3 and bdl-4). For the first entry, the request SHALL match a request to the $status operation on the Subscription. For further entries, the request SHOULD reflect the interaction that triggered the event (e.g. PUT for an update), per the Backport IG.
Unlike a handshake or heartbeat, an event-notification reports an actual event, so when type is event-notification, the Parameters resource SHALL additionally carry:
-
notification-event.event-number— sequence number that increases by one for each event notified under the Subscription, used to detect missed events. An event for which the notification is withheld because the authorization or processing-basis verification fails (see Implementation Obligations) is not assigned an event-number; a notification that was permitted but failed delivery is. This is a TA addition; the Backport IG does not address withheld notifications. -
notification-event.timestamp— the moment the event occurred at the Subscription Server. Notifications for the same event under different Subscriptions SHALL carry the same timestamp (see Replacing a Subscription). Optional in the Backport IG; required by this TA.
When type is heartbeat, the Parameters resource SHALL additionally carry events-since-subscription-start: the total number of events assigned an event-number for the Subscription since its creation (see event-number above), not counting handshake and heartbeat notifications. The Backport IG counts all events generated for the Subscription regardless of delivery; under this TA, an event whose notification is withheld is not counted as generated for the Subscription, while a notification that failed delivery is. This allows the Subscription Client to detect missed event-notifications, including the most recent one, in the absence of later events (optional in the Backport IG; required by this TA).
Whether notification-event.focus, or the resource content itself, is also present depends on the Subscription's payload mode (see Notification Payload Model):
-
Id-only mode. The Parameters resource SHALL carry notification-event.focus. Each further Bundle entry SHALL carry the resource URL in fullUrl and request, and SHALL NOT carry the resource content.
-
Full-resource mode. The Parameters resource SHALL carry notification-event.focus, and the Bundle SHALL carry the resource content itself in entry.resource.
-
Empty mode. The Parameters resource SHALL NOT carry notification-event.focus, notification-event.additional-context or notification-event.related-query, and the Bundle SHALL NOT contain any entry other than the Parameters resource.
Authorization value (out-of-band only)
For out-of-band Subscriptions, an event-notification, and its replay through $events, MAY carry an authorization value that the Subscription Client needs for the subsequent pull, as two additional parts of notification-event: authorization-type (Coding), identifying the authorization mechanism the value belongs to, and authorization-value (string), carrying the value itself.
These parts are not defined in version 1.1.0 of the Backport IG; they follow the names used in its 1.2.0 ballot (notification-authorization-hint), and remain conformant to 1.1.0, whose slicing of notification-event parts is open. Where a published version of the Backport IG changes these names, this TA follows that version.
The meaning of the value, the applicable authorization-type codes, how the value is used in the subsequent pull, and how long it remains valid are defined by GF Authorization, not by this TA (see Authorization for Pulls under Out-of-Band Subscriptions). This TA only requires that the value:
-
SHALL satisfy the opacity and unpredictability requirements (see Requirements for Using Id-Only);
-
SHALL be single-use or time-bounded, since it is exposed to every party that handles the notification (see Data exposed by an id-only notification);
-
SHALL NOT be present for in-band Subscriptions.
Related query
An event-notification in id-only or full-resource mode, and its replay through $events, MAY carry one or more queries the Subscription Client can use to retrieve data related to the event, as related-query parts of notification-event, each with a query (string) and optionally a query-type (Coding), only where the use-case-specific technical agreement permits this for the topic (see Requirements on Use-Case-Specific Technical Agreements).
This part is not defined in version 1.1.0 of the Backport IG; it follows the names used in its 1.2.0 ballot, and remains conformant to 1.1.0, whose slicing of notification-event parts is open. Where a published version of the Backport IG changes these names, this TA follows that version.
A query SHALL NOT contain real-world identifying numbers, such as a BSN or a patient number, since it is exposed to every party that handles the notification (see Data exposed by an id-only notification). Where a query refers to a resource by its id, that id SHALL satisfy the requirements in Requirements for Using Id-Only. Retrieval through a query is subject to the same data-minimisation concern as any search (see When a Reference Is Preferable to Empty).
SubscriptionTopic
In FHIR R4, there is no SubscriptionTopic resource: the Backport IG leaves topic definitions out of scope for R4, and a Subscription refers to a topic solely by its canonical URL. The definition of a topic is designated in the use-case-specific technical agreement that applies it (see Requirements on Use-Case-Specific Technical Agreements), in one of two forms:
-
as text in that agreement; or
-
as a SubscriptionTopic resource published under FHIR R4B or R5 by a server that supports that version, identified in the agreement by its canonical URL and version (
SubscriptionTopic.version). The Backport IG notes that a server needing topic definitions beyond what R4 supports may expose an R4B endpoint for this purpose.
In either form, the definition:
-
SHALL assign the topic a unique canonical URL;
-
SHALL specify the single resource type it monitors (e.g. Task or Observation). This TA restricts each topic to one monitored resource type; this is a choice of this TA, not a constraint of FHIR or the Backport IG;
-
SHALL specify which interactions trigger it (
create,update,delete), and any further trigger condition, such as a coded value (e.g. a SNOMED procedure code to specialise a generic Task topic for transfer-of-care use cases, or a generic Observation topic for a specific lab test); -
SHALL state, for the events it defines, how the patient an event concerns is resolved: via a filter parameter set on the Subscription itself (e.g. a
patientfilter, resolvable at Subscription-creation time), via a designated element on the triggering resource (e.g.Task.for, resolvable only once the event occurs), or not at all, where the event by design concerns no identified patient (e.g. a request for care based on the care need only, before the patient is disclosed). Where a topic covers events of both kinds, for instance a workflow in which the patient is identified only at a later stage, the definition SHALL state from which point the patient is resolvable;
-
MAY define filter parameters a Subscription is allowed to use in
backport-filter-criteria, each with its name, the element of the monitored resource it applies to, and the form of its value (e.g. filter parameter owner onTask.owner.identifier, with a URA as value). Where a filter parameter identifies an organisation, it SHOULD apply to the identifier of the reference and take the organisation's URA as value (e.g.owner=http://fhir.nl/fhir/NamingSystem/ura|12104037), since a literal reference to an Organization on the Subscription Server is not known to the Subscription Client.
Where the definition is a published SubscriptionTopic resource, the use-case-specific technical agreement states any requirement above that the resource does not express, such as how the patient an event concerns is resolved. The version identified in the agreement is the one that applies; a later version of the resource applies only once the agreement identifies it. This TA does not require the Subscription Server or the Subscription Client to retrieve the resource at runtime. A topic is not agreed merely because its definition is resolvable: only topics designated in the applicable use-case-specific technical agreement are accepted (see Preconditions).
Choosing a Resource Type to Monitor
A SubscriptionTopic SHOULD monitor a coordination/workflow resource (e.g. Task) when what matters to the receiver is a change in process state — who owns something, what step it is in, whether it is complete. It SHOULD monitor a data resource directly (e.g. Observation, DocumentReference) when what matters is that specific clinical content has become available or changed, independent of any workflow around it.
These are not mutually exclusive: a single real-world event, such as a referral becoming available for pickup, can be framed as either a workflow-state change (the coordinating Task moving to a "ready" state) or a data-availability change (the referral content itself appearing), and different use cases may reasonably choose either framing depending on what the receiving system needs to act on. This choice is made in the use-case-specific technical agreement (see Requirements on Use-Case-Specific Technical Agreements); this TA does not mandate one framing over the other.
Subscription
A Subscription is the FHIR resource that models a long-running agreement between a Subscription Server (sender) and a Subscription Client (receiver) about which notifications should be delivered, and where. The content SHALL adhere to these rules:
-
SHALL conform to the Backport IG Subscription profile (
backport-subscription). -
SHALL be bound to exactly one pre-agreed SubscriptionTopic, by carrying the topic's canonical URL in
Subscription.criteria. -
SHALL concern only events of zorgaanbieders for which the base URL it is created at is registered in GF Addressing (see Subscription Server). Where that base URL is registered for several zorgaanbieders, the Subscription concerns events of each of them. These zorgaanbieders are determined at the time of each notification, not when the Subscription is created: a zorgaanbieder for which the base URL is registered later falls under existing Subscriptions from then on, and a zorgaanbieder whose registration is removed no longer does. Such a change requires no new Subscription, and does not by itself permit any notification: authorization and the processing basis are verified per notification, for the zorgaanbieder whose data that notification concerns (see Implementation Obligations), and the Subscription Client verifies per notification that it originates from one of these zorgaanbieders (see Subscription Client). The registration itself is governed by GF Addressing.
-
MAY carry one or more scoping filters via the extension
backport-filter-criteriaonSubscription.criteria, in the filter syntax defined by the Backport IG and using filter parameters allowed by the topic definition (e.g.owner=http://fhir.nl/fhir/NamingSystem/ura|12104037). -
channel.typeSHALL berest-hook, pointing at the Subscription Client's notification endpoint. (R4 backport allows a server to support any channel type it chooses — rest-hook, websocket, email, message; this TA restricts the channel type to rest-hook.) -
channel.payload SHALL be
application/fhir+jsonorapplication/fhir+xml. For in-band creation, the Subscription Client sets a format it supports. For out-of-band creation, the Subscription Server sets a format the Subscription Client supports, as established by prior agreement or by the Subscription Client's endpoint registration in GF Addressing (Endpoint.payloadMimeType). The extension backport-payload-content is set to the payload mode agreed for the Subscription (empty,id-only, orfull-resource; see Notification Payload Model). The Backport IG requires this extension, for in-band and out-of-band creation alike. -
Subscription.idis carried in every notification, in every payload mode, and is visible to every party that handles a notification (see Data exposed by an id-only notification). It SHALL therefore satisfy the opacity and unpredictability requirements in Requirements for Using Id-Only. Where a Subscription concerns a single patient, its id is a stable reference to that patient's notifications; this TA does not require per-recipient or rotating Subscription ids, but an exchange agreement MAY. -
MAY carry the extension
backport-heartbeat-periodonchannel(0..1,unsignedInt, seconds) to request or convey the heartbeat interval (see Heartbeat Notification).
Transactions
The transactions below take place between the Subscription Server and the Subscription Client over an mTLS-secured channel (see Preconditions). The wire format and behavioural details follow the Subscriptions R5 Backport for R4; below we limit ourselves to the requirements that are additional or more restrictive in this context.
Creating a Subscription
A Subscription is created on the sender's side. This happens either out-of-band (the sender sets up the Subscription, under a SubscriptionTopic the receiver has agreed to receive, based on a notification endpoint obtained via GF Addressing) or in-band (the receiver, having resolved the Subscription Server's endpoint via GF Addressing if not already known, POSTs a Subscription to the Subscription Server, which verifies via GF Authorization that the receiver is authorized for the SubscriptionTopic before accepting it).
The Subscription resource may be submitted as application/fhir+json or application/fhir+xml, independent of the notification format set in channel.payload (see Subscription Server).
A Subscription is intended as a long-running agreement between the Subscription Server and Subscription Client about a topic, not as a per-event object.
Use Case Roles
|
Actor |
Role |
|---|---|
|
Subscription Client |
Is the target of the Subscription; creates it in-band |
|
Subscription Server |
Creates the Subscription out-of-band; persists it and validates it against the agreed SubscriptionTopic |
Referenced Standards
-
HL7® FHIR® Subscriptions R5 Backport Implementation Guide 1.1.0 (R4)
-
GF Addressing (for endpoint resolution, in-band or out-of-band)
-
HTTPS over mTLS
Exchange - Request
Trigger: A receiving organisation (or the sender, on its behalf, out-of-band) wants to be notified about a pre-agreed SubscriptionTopic.
Description: This transaction follows the standard FHIR create interaction on /Subscription, per the Backport IG (see Referenced Standards). The Subscription carries the SubscriptionTopic canonical URL in Subscription.criteria, optionally a scoping filter (backport-filter-criteria).
Beyond the IG, this TA requires:
-
channel.type = rest-hook; the IG permits other channel types (websocket, email, message), this TA restricts to rest-hook only; -
channel.payload = application/fhir+jsonorchannel.payload = application/fhir+xmlwith extensionbackport-payload-contentset per the payload mode agreed for that Subscription (see Notification Payload Model).
Technical Details:
|
Field |
Value / Description |
|---|---|
|
HTTP Method |
POST |
|
Endpoint |
|
|
Headers |
|
Exchange - Response
Description: Standard FHIR create responses apply, plus one TA-specific business rule: 422 Unprocessable Entity when the SubscriptionTopic is not pre-agreed.
Technical Details:
|
HTTP Status Code |
Meaning |
|---|---|
|
201 Created |
Subscription successfully created; status set to |
|
400 Bad Request |
Request could not be parsed or failed FHIR validation |
|
422 Unprocessable Entity |
SubscriptionTopic not agreed/known, or business rules violated; OperationOutcome returned |
Payload: On success: the created Subscription resource (201 Created). On error: a FHIR OperationOutcome with details.
Rules
The Subscription resource SHALL satisfy the content requirements set out in Resource Definitions → Subscription. In addition, a Subscription created via this transaction:
-
SHALL be set to
activeonly after a successful handshake (see Handshake Notification), and set to off (not deleted) upon retirement, by either party (see Sequence Diagram, step 7). -
For in-band creation, the channel.endpoint SHALL be verified against GF Addressing before the Subscription is accepted (see Preconditions); a Subscription whose endpoint fails that verification SHALL be rejected with 422 Unprocessable Entity.
Example
A Subscription request combining the topic canonical, a scoping filter, and the id-only payload mode:
{
"resourceType": "Subscription",
"status": "requested",
"reason": "Notification of Task status changes",
"criteria": "https://example.org/fhir/SubscriptionTopic/task-status-change",
"_criteria": {
"extension": [
{
"url": "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-filter-criteria",
"valueString": "owner=http://fhir.nl/fhir/NamingSystem/ura|12104037"
}
]
},
"channel": {
"type": "rest-hook",
"endpoint": "https://receiver.example.org/fhir/notifications",
"payload": "application/fhir+json",
"_payload": {
"extension": [
{
"url": "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-payload-content",
"valueCode": "id-only"
}
]
}
}
}
Additional Notes
A Subscription is bound to exactly one SubscriptionTopic (see Resource Definitions → Subscription); a topic monitors a single resource type (see Resource Definitions → SubscriptionTopic).
Updating a Subscription
A Subscription, whether created in-band or out-of-band, can be updated by the Subscription Client of the zorgaanbieder that receives its notifications, for two purposes only: retiring the Subscription by setting its status to off, and changing the notification format in channel.payload. Any other change requires a new Subscription (see Replacing a Subscription). Changes the Subscription Server makes itself, to retire a Subscription or to change the format of an out-of-band Subscription, are not a transaction under this TA.
Use Case Roles
|
Actor |
Role |
|---|---|
|
Subscription Client |
Updates a Subscription of which it receives the notifications |
|
Subscription Server |
Validates the update against the permitted changes and applies it |
Referenced Standards
-
HL7® FHIR® R4, RESTful API, update interaction
-
HL7® FHIR® Subscriptions R5 Backport Implementation Guide 1.1.0 (R4)
-
HTTPS over mTLS
Exchange - Request
Trigger: The Subscription Client wants to retire a Subscription of which it receives the notifications, or to change its notification format.
Description: This transaction follows the standard FHIR update interaction on /Subscription/[id]. Beyond FHIR and the Backport IG, this TA restricts which changes are permitted (see Rules).
|
Field |
Value / Description |
|---|---|
|
HTTP Method |
PUT |
|
Endpoint |
|
|
Headers |
|
Exchange - Response
Description: Standard FHIR update responses apply, plus the TA-specific business rules below.
|
HTTP Status Code |
Meaning |
|---|---|
|
200 OK |
Update applied; the updated Subscription is returned |
|
400 Bad Request |
Request could not be parsed or failed FHIR validation |
|
403 Forbidden |
The requesting party is not the Subscription Client of the zorgaanbieder that receives the Subscription’s notifications |
|
404 Not Found |
Unknown Subscription id |
|
422 Unprocessable Entity |
The update contains a change other than those permitted, or the Subscription is already off; OperationOutcome returned |
Payload: On success: the updated Subscription resource. On error: a FHIR OperationOutcome.
Rules
-
Only the Subscription Client of the zorgaanbieder that receives the Subscription's notifications MAY update it, as established from the authentication context of the request (see Subscription Client): for an in-band Subscription, the zorgaanbieder that created it; for an out-of-band Subscription, the zorgaanbieder for which the Subscription Server created it.
-
The permitted changes are: status set to off, and channel.payload set to another format the Subscription Client supports (see Resource Definitions → Subscription). All other elements, including criteria, backport-filter-criteria, channel.endpoint, channel.type, backport-payload-content and backport-heartbeat-period, SHALL be unchanged; otherwise the update SHALL be rejected with 422.
-
The status of a Subscription is maintained by the Subscription Server (see Implementation Obligations). The Subscription Server SHALL treat status in an update as a request: off retires the Subscription; any other value is ignored and the current status is retained. Likewise,
meta,textanderrorare maintained by the Subscription Server: it SHALL ignore their values in an update, including their absence, and retain its own. They are therefore not subject to the requirement that all other elements remain unchanged. -
A Subscription that is off SHALL NOT be updated; such an update SHALL be rejected with 422.
-
A changed format applies to every notification sent after the 200 OK response.
Example
Retiring the Subscription from the example in Creating a Subscription:
PUT https://sender.example.org/fhir/Subscription/7f3e9a2c-5d18-4b6f-9c3a-8e2d4f6b1a59
{
"resourceType": "Subscription",
"id": "7f3e9a2c-5d18-4b6f-9c3a-8e2d4f6b1a59",
"status": "off",
"reason": "Notification of Task status changes",
"criteria": "https://example.org/fhir/SubscriptionTopic/task-status-change",
"_criteria": {
"extension": [
{
"url": "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-filter-criteria",
"valueString": "owner=http://fhir.nl/fhir/NamingSystem/ura|12104037"
}
]
},
"channel": {
"type": "rest-hook",
"endpoint": "https://receiver.example.org/fhir/notifications",
"payload": "application/fhir+json",
"_payload": {
"extension": [
{
"url": "http://hl7.org/fhir/uv/subscriptions-backport/StructureDefinition/backport-payload-content",
"valueCode": "id-only"
}
]
}
}
}
Additional Notes
A replacement Subscription is created through Creating a Subscription; the replaced in-band Subscription is then retired through this transaction (see Replacing a Subscription).
Replacing a Subscription
A Subscription is replaced, rather than modified, when its payload mode changes (see Payload Mode Agreement and Enforcement) or when its SubscriptionTopic is succeeded by another (see Preconditions). It MAY also be replaced for other reasons. The party that created the Subscription (the Subscription Client for in-band, the Subscription Server for out-of-band) performs the replacement.
Rules
-
After the Subscription Client has set a Subscription to off, the Subscription Server SHALL NOT create a new Subscription for the same SubscriptionTopic, filter criteria and receiving zorgaanbieder, unless that zorgaanbieder has agreed to this outside this TA. This does not prevent the Subscription Server from creating Subscriptions with other filter criteria for that zorgaanbieder, such as for another patient.
-
The replacement Subscription SHALL be active before the Subscription it replaces is set to
off, so that no events are lost during replacement. The replaced Subscription SHALL be set tooffonce the replacement has been confirmedactive; for in-band Subscriptions through Updating a Subscription. -
During the overlap, an event matching both Subscriptions results in a notification under each, each with its own event-number. The Subscription Client SHALL deduplicate these notifications using the combination of notification-event.focus and notification-event.timestamp (see Resource Definitions → Notification).
-
Where either Subscription is in empty mode, notifications carry no focus and cannot be deduplicated. A duplicate empty notification only leads to a redundant query, which the Subscription Client SHALL process idempotently.
-
This TA does not end the validity of an authorization value when a Subscription is replaced; its validity is governed by GF Authorization.
-
The Subscription Server SHALL continue to support
$statuson the replaced Subscription, and$eventswhere supported, for the retention period agreed for replayable events, so that a gap detected before replacement can still be recovered.
Handshake Notification
After a Subscription is created, the Subscription Server sends a handshake Bundle to the Subscription Client's notification endpoint. On success, Subscription.status is set to active. On any failure, the status is set to error, as required by the Backport IG; for transient errors, retries SHALL be attempted with exponential backoff, and the status is set to active upon a successful retry, or to off when retries are exhausted (see Implementation Obligations).
Use Case Roles
|
Actor |
Role |
|---|---|
|
Subscription Server |
Sends the handshake and updates |
|
Subscription Client |
Receives the handshake at its notification endpoint |
Referenced Standards
Exchange - Request
Trigger: The Subscription Server has accepted a new Subscription and its status is requested.
Description: This transaction follows the Backport IG's handshake flow: the Subscription Server sends a handshake Bundle (type = handshake) to the Subscription Client's notification endpoint to confirm reachability. Beyond the IG, this TA requires retry on failure using exponential backoff specifically (see Implementation Obligations).
Technical Details:
|
Field |
Value / Description |
|---|---|
|
HTTP Method |
POST |
|
Endpoint |
Subscription Client's notification endpoint ( |
|
Headers |
Per |
Exchange - Response
Description: Standard Backport IG handshake responses apply (status transitions to active on success and to error on any error); the TA-specific additions are the exponential-backoff retry strategy and the subsequent transition to active or off (see Implementation Obligations).
Technical Details:
|
HTTP Status Code |
Meaning |
|---|---|
|
200 OK |
Handshake received and accepted |
|
429, 5xx, network errors |
Handshake failed (transient); Subscription Server sets status to |
|
Other 4xx |
Handshake rejected (permanent); Subscription Server sets status to |
Payload: Typically empty (200 OK); on error, a FHIR OperationOutcome.
Example
A handshake Bundle, sent while Subscription.status is still requested:
{
"resourceType": "Bundle",
"type": "history",
"entry": [
{
"fullUrl": "urn:uuid:9e41b2d7-3c85-4f1a-b6e0-2d7c8a5f4e13",
"resource": {
"resourceType": "Parameters",
"parameter": [
{ "name": "subscription", "valueReference": { "reference": "https://sender.example.org/fhir/Subscription/7f3e9a2c-5d18-4b6f-9c3a-8e2d4f6b1a59" } },
{ "name": "topic", "valueCanonical": "https://example.org/fhir/SubscriptionTopic/task-status-change" },
{ "name": "status", "valueCode": "requested" },
{ "name": "type", "valueCode": "handshake" }
]
},
"request": {
"method": "GET",
"url": "https://sender.example.org/fhir/Subscription/7f3e9a2c-5d18-4b6f-9c3a-8e2d4f6b1a59/$status"
},
"response": { "status": "200" }
}
]
}
Additional Notes
-
This resource does not need to be stored persistently by the receiver beyond updating its own Subscription state.
Event Notification
For each event matching the topic and filter, the Subscription Server sends one event-notification Bundle to the Subscription Client's notification endpoint.
Use Case Roles
|
Actor |
Role |
|---|---|
|
Subscription Server |
Detects the matching event and sends the event-notification, incrementing event-number |
|
Subscription Client |
Receives the event-notification and checks continuity of event-number |
Referenced Standards
Exchange - Request
Trigger: An event occurs at the Subscription Server matching the active Subscription's topic and filter criteria.
Description: This transaction follows the Backport IG's event-notification flow. The Subscription Server sends an event-notification Bundle (type = event-notification) carrying an event-number that increases by one for each event notified (assigned in a concurrency-safe manner; see Resource Definitions → Notification) and, unless the payload mode is empty, a notification-event.focus reference to the source resource.
Technical Details:
|
Field |
Value / Description |
|---|---|
|
HTTP Method |
POST |
|
Endpoint |
Subscription Client's notification endpoint |
|
Headers |
Per |
Exchange - Response
Description: The receiver acknowledges receipt and, if it wishes to access the content, performs a separate, authorised pull via the sender's FHIR endpoint (out of scope of this TA, see TA Pull).
Technical Details:
|
HTTP Status Code |
Meaning |
|---|---|
|
200 OK |
Notification received and accepted |
|
429, 5xx, network errors |
Delivery failed (transient); Subscription Server SHALL retry with exponential backoff, with status |
|
Other 4xx |
Notification rejected (permanent); Subscription Server SHALL NOT retry, sets status to |
A Subscription Client SHALL NOT reject a notification because of a gap in, or repetition of, the event-number sequence. Gaps are handled as described under Subscription Client; repeated delivery of a previously processed notification is accepted with 200 OK and processed idempotently (see Implementation Obligations).
Payload: Typically empty (200 OK).
Rules
The notification SHALL carry the fields listed in Resource Definitions → Notification, with type = event-notification. In addition, an event-notification:
-
SHALL assign the event-number in a concurrency-safe manner. The IG does not address concurrent assignment, so this is a TA addition, not an IG requirement.
Example
An id-only event-notification Bundle for a SubscriptionTopic that monitors Task (used here only as an example resource type; the actual type depends on the agreed SubscriptionTopic), trimmed to the relevant fields. The first entry reports the event; the second entry identifies the resource that triggered it. The focus reference uses the id from the Random (UUIDv4) example under Id Examples:
{
"resourceType": "Bundle",
"type": "history",
"entry": [
{
"fullUrl": "urn:uuid:c3a5d8f1-9b2e-4d67-8a4c-5e1f7b9d2a36",
"resource": {
"resourceType": "Parameters",
"parameter": [
{ "name": "subscription", "valueReference": { "reference": "https://sender.example.org/fhir/Subscription/7f3e9a2c-5d18-4b6f-9c3a-8e2d4f6b1a59" } },
{ "name": "topic", "valueCanonical": "https://example.org/fhir/SubscriptionTopic/task-status-change" },
{ "name": "status", "valueCode": "active" },
{ "name": "type", "valueCode": "event-notification" },
{
"name": "notification-event",
"part": [
{ "name": "event-number", "valueString": "42" },
{ "name": "timestamp", "valueInstant": "2026-07-16T09:15:00Z" },
{ "name": "focus", "valueReference": { "reference": "https://sender.example.org/fhir/Task/5f2f9a4e-8c1d-4b6e-9d3a-7c0e2f4b8a1d" } }
]
}
]
},
"request": {
"method": "GET",
"url": "https://sender.example.org/fhir/Subscription/7f3e9a2c-5d18-4b6f-9c3a-8e2d4f6b1a59/$status"
},
"response": { "status": "200" }
},
{
"fullUrl": "https://sender.example.org/fhir/Task/5f2f9a4e-8c1d-4b6e-9d3a-7c0e2f4b8a1d",
"request": {
"method": "PUT",
"url": "Task/5f2f9a4e-8c1d-4b6e-9d3a-7c0e2f4b8a1d"
},
"response": { "status": "200" }
}
]
}
Two elements relate to the Task resource itself:
-
focus: the reference to the resource that triggered the event, using its logical id, which satisfies stability, opacity, and unpredictability. Its presence is what makes the notification id-only rather than empty. -
The second entry:
fullUrlcarries the same resource URL, and request records the interaction that triggered the event (here an update,PUT), as required forhistoryBundles. The entry carries no resource content. It is written by the Subscription Server as part of the notification; it is not a record of any retrieval by the receiver. A receiver that subsequently retrieves the resource does so by a direct read on this URL, which discloses exactly this one resource.
Additional Notes
Authorization of content access following a notification is governed by TA Pull and GF Authorization (see Authorization for Pulls under Out-of-Band Subscriptions).
Heartbeat Notification (Optional)
At pre-agreed intervals, the Subscription Server sends a heartbeat Bundle. This serves as a keep-alive signal for the channel and allows the Subscription Client to detect a silent outage even when no events are occurring.
Per the Backport IG, whether heartbeats are used is settled through a request/accept mechanism at Subscription creation: the Subscription Client requests a heartbeat interval (via the backport-heartbeat-period extension on Subscription.channel), and the Subscription Server MAY accept that request as given, modify it, or omit heartbeats altogether. A prior agreement between the parties MAY restrict this mechanism — for example, by fixing the interval in advance or ruling out heartbeats entirely, or requiring the Subscription Server to support and accept heartbeat requests.
The Subscription Client SHALL treat the heartbeat interval actually in effect as the value of backport-heartbeat-period on the Subscription resource as returned by the Subscription Server — whether from the 201 Created response to an in-band request, or from a subsequent read — not the value the Client itself requested. For out-of-band Subscriptions, the value the Subscription Server sets is authoritative from the start, since there was no prior Client request to compare it against.
For out-of-band Subscriptions, the request/accept mechanism above does not apply, because there is no live request from the Subscription Client: the Subscription Server creates the Subscription unilaterally. Whether heartbeats are used, and at what interval, is therefore settled entirely by the use-case-specific technical agreement (see Requirements on Use-Case-Specific Technical Agreements), and the Subscription Server sets the heartbeat interval on the Subscription it creates accordingly.
Heartbeats give the Subscription Client assurance it cannot otherwise obtain: that the channel is working, that the Subscription is still active at the Subscription Server, and, through events-since-subscription-start (see Resource Definitions → Notification), that no notification has been missed, including the most recent one. Without heartbeats, the Subscription Client detects a missed notification only when a later event-notification arrives, and does not detect a missed last notification at all. Retries do not substitute for this: they inform the Subscription Server of failed deliveries, not the Subscription Client.
This assurance applies equally to sender-initiated and receiver-initiated notifications: in both, a silent outage at the Subscription Server is visible only to the Subscription Client. Heartbeats do not demonstrate that the Subscription Server correctly detects the events a topic defines; a server that fails to detect an event still sends its heartbeats.
Whether heartbeats are used, and at what interval, depends on how quickly a missed notification must be detected for the process concerned, and on how frequently events are expected. Where events are frequent, event-number continuity already reveals gaps quickly; where they are infrequent, or a missed last notification is consequential, heartbeats are the only means of timely detection. This choice is made in the use-case-specific technical agreement (see Requirements on Use-Case-Specific Technical Agreements).
Use Case Roles
|
Actor |
Role |
|---|---|
|
Subscription Server |
Sends heartbeat at the agreed interval, with retry |
|
Subscription Client |
Checks at agreed intervals whether an expected heartbeat was missed (see Subscription Client) |
Referenced Standards
Exchange - Request
Trigger: The pre-agreed heartbeat interval for an active Subscription elapses.
Description: This transaction follows the Backport IG's heartbeat flow (see Referenced Standards above); the TA-specific additions are the exponential-backoff retry strategy and the status transitions on delivery failure (see Implementation Obligations).
Technical Details:
|
Field |
Value / Description |
|---|---|
|
HTTP Method |
POST |
|
Endpoint |
Subscription Client's notification endpoint |
|
Headers |
Per |
Exchange - Response
Description: The receiver resets its missed-heartbeat timer; if a heartbeat is missed, the receiver SHOULD query $status.
Technical Details:
|
HTTP Status Code |
Meaning |
|---|---|
|
200 OK |
Heartbeat received |
|
429, 5xx, network errors |
Heartbeat delivery failed (transient); Subscription Server SHALL retry with exponential backoff, with status |
|
Other 4xx |
Heartbeat rejected (permanent); Subscription Server SHALL NOT retry and sets status to |
Payload: Typically empty (200 OK).
Example
A heartbeat Bundle for an active Subscription:
{
"resourceType": "Bundle",
"type": "history",
"entry": [
{
"fullUrl": "urn:uuid:0364d735-381d-4a15-89fd-597e557b0ce2",
"resource": {
"resourceType": "Parameters",
"parameter": [
{ "name": "subscription", "valueReference": { "reference": "https://sender.example.org/fhir/Subscription/7f3e9a2c-5d18-4b6f-9c3a-8e2d4f6b1a59" } },
{ "name": "topic", "valueCanonical": "https://example.org/fhir/SubscriptionTopic/task-status-change" },
{ "name": "status", "valueCode": "active" },
{ "name": "type", "valueCode": "heartbeat" },
{ "name": "events-since-subscription-start", "valueString": "42" }
]
},
"request": {
"method": "GET",
"url": "https://sender.example.org/fhir/Subscription/7f3e9a2c-5d18-4b6f-9c3a-8e2d4f6b1a59/$status"
},
"response": { "status": "200" }
}
]
}
Additional Notes
Heartbeat sending is optional; whether and at what interval are set by the use-case-specific technical agreement.
$status and $events Operations ($events Optional)
The receiver uses:
-
$statusto query the current state of a Subscription at the Subscription Server — typically after a missed heartbeat; -
$eventsto retrieve a specific event-number or a range thereof — typically after detecting a gap in the sequence.
Use Case Roles
|
Actor |
Role |
|---|---|
|
Subscription Client |
Invokes |
|
Subscription Server |
Supports the |
Referenced Standards
-
HL7® FHIR® Subscriptions R5 Backport Implementation Guide 1.1.0 (R4) (
GET [base]/Subscription/[id]/$statusand$eventsoperations)
Exchange - Request
Trigger: The receiver detects a gap in the event-number sequence, or a missing expected heartbeat.
Description: The Subscription Client invokes $status to query the current state of the Subscription, or $events to retrieve a specific event-number or range thereof.
Technical Details:
|
Field |
Value / Description |
|---|---|
|
HTTP Method |
GET |
|
Endpoint |
|
|
Headers |
Per the Subscription Client's choice; the Subscription Server supports both |
|
Parameters |
Per the Backport IG's |
Exchange - Response
Description: The Subscription Server returns the current status of the Subscription ($status), or replays the requested event-notification(s) ($events).
Technical Details:
|
HTTP Status Code |
Meaning |
|---|---|
|
200 OK |
Status or requested event(s) returned |
|
404 Not Found |
Unknown Subscription id |
|
422 Unprocessable Entity |
Requested event-number range invalid or no longer available |
Payload: On success: for $status, a Bundle of type searchset containing a Parameters resource conforming to backport-subscription-status-r4 (see OperationDefinition backport-subscription-status); for $events, a single Bundle of type history with the subscription status as its first entry, followed by the requested event-notifications (see OperationDefinition backport-subscription-events). On error: a FHIR OperationOutcome.
Additional Notes
-
Used for recovery only; not part of the regular operational flow.
-
The retention period for replayable events is set by the use-case-specific technical agreement (see Requirements on Use-Case-Specific Technical Agreements).
If a Subscription Server does not support the $events operation, a detected gap in the event-number sequence cannot be recovered through this TA's notification mechanism. Reconciliation instead falls to the applicable use-case-specific technical agreement or the underlying resource API, for example by querying the source system for resources of the monitored type changed since the last successfully processed notification. Such a query is subject to the same data-minimisation concern as the search that empty mode requires (see When a Reference Is Preferable to Empty). It also has two limitations. First, a search does not return deleted resources, so missed events for a topic triggered by delete cannot be reconciled this way; a history interaction with _since does return deletions, at the cost of disclosing every intermediate version. Second, notification-event.timestamp is the moment the event occurred, which need not coincide with the resource's meta.lastUpdated, so a query period based on it needs a margin, with any duplicates processed idempotently. This TA does not define such a reconciliation mechanism (see Requirements on Use-Case-Specific Technical Agreements). A Subscription Client SHOULD take a Subscription Server's non-support of $events into account when creating a Subscription, or accepting the handshake of an out-of-band Subscription, with payload mode id-only or full-resource: in empty mode the receiver retrieves changes by query after each notification anyway, whereas a missed id-only or full-resource notification is not compensated by the next one.
Using this TA
This TA defines the generic notification mechanism; it does not itself activate any exchange. Putting it into use for a specific case requires a use-case-specific technical agreement that meets the requirements below.
Requirements on Use-Case-Specific Technical Agreements
The requirements in this section apply to the authors of a use-case-specific technical agreement that applies this TA. They are assessed when such an agreement is drawn up or changed, not in the certification of implementations. A use-case-specific technical agreement that applies this TA:
-
SHALL define each SubscriptionTopic it uses, as text or by identifying a published SubscriptionTopic resource by canonical URL and version, meeting the requirements in Resource Definitions → SubscriptionTopic, including how the patient an event concerns is resolved and the value form of each filter parameter. For events that by design concern no identified patient, it SHALL state why the data involved is not identifying, and on what basis it may be disclosed;
-
SHALL, where it withdraws a SubscriptionTopic that another topic succeeds, for instance when topics are merged or split, keep both designated for a transition period it states, so that Subscriptions can be replaced before those on the withdrawn topic are set to off (see Preconditions and Replacing a Subscription);
-
SHALL state, for each topic, whether it monitors a workflow resource or a data resource, and why (see Choosing a Resource Type to Monitor);
-
SHALL state, for each topic, which payload mode or modes are permitted (see Payload Mode Agreement and Enforcement). Where a topic is triggered by delete, empty mode SHALL NOT be permitted unless the agreement states how the receiver determines which resource was deleted, since a search does not return deleted resources;
-
SHALL state, for each topic that permits full-resource, what data the monitored resource contains, and, where that includes personal data, that the applicable processing basis covers its disclosure to the receiver (see Privacy, Consent, and Authorization);
-
SHALL state, for each topic, whether related-query is permitted and, if so, which queries it carries (see Resource Definitions → Notification → Related query);
-
SHALL state, for each topic, whether Subscriptions are created in-band, out-of-band, or both (see Subscription Server);
-
SHALL state, for each topic, whether heartbeats are used and at what interval; for out-of-band Subscriptions, this agreement is the only place where this is settled (see Heartbeat Notification);
-
SHALL state whether $events is required and, if so, the retention period for replayable events. Where $events is not required, it SHALL state the reconciliation route for missed notifications, or state that none applies. A reconciliation route based on search SHALL be limited to the monitored resource type, the Subscription's filter criteria, and the period of the gap, and SHALL state how missed deletions are reconciled where the topic is triggered by delete (see $status and $events Operations);
-
SHALL state the maximum retry duration for the delivery of handshake, heartbeat and event notifications, after which retries are exhausted and the Subscription is set to off (see Implementation Obligations);
-
SHALL decide, for each topic that monitors a broadly accessible resource, whether id-only with a shared id, id-only with per-recipient ids, or empty mode is used (see When a Reference Is Preferable to Empty). Where per-recipient ids are used, it SHALL state how retrieval (see TA Pull) returns the resource under the same per-recipient id, and how references to other resources within it are handled (see Appendix A, Constructing an Id: Per-Recipient);
-
SHALL identify the processing basis and authorization conditions that apply, per GF Authorization and GF Toestemming (and, where applicable, EHDS) (see Privacy, Consent, and Authorization).
Any routing information the receiver needs to determine which internal process a notification concerns is also defined there; this TA carries no such information in the notification itself.
Appendix A: Id Construction — Illustrative Examples
This appendix illustrates constructions that satisfy or fail the requirements in Requirements for Using Id-Only. It is informative: the requirements themselves, not this appendix, are what an id must be checked against.
Schemes That Fail
Several id constructions are known to fail the stability, opacity, or unpredictability requirements stated in Requirements for Using Id-Only, and therefore cannot be used as the reference in an id-only notification. This list is illustrative, not exhaustive — other constructions can fail the same requirements; any id should be checked against the requirements themselves, not just against this list.
Ordered ids (sequential counters) — reveal creation order and volume, are guessable, and let a reader infer that a resource exists between two ids it has seen. Fails the opacity and unpredictability requirements.
Time-encoding ids (UUIDv1, UUIDv7) — reveal the moment of creation. Fails the opacity requirement.
Concatenated ids (e.g., department plus patient number plus date) — reveal content directly. Fails the opacity requirement.
Derived ids (an unkeyed hash of sensitive input; UUIDv5 is in this class) — reveal content to anyone who can brute-force the input space, such as the space of patient numbers. Fails the unpredictability requirement.
Low-entropy ids — guessable: ids with less than 64 bits of entropy, or generated by a random number generator that is not cryptographically secure. An attacker with an overbroad or forged token can probe candidates, and operational mistakes silently hit valid resources; entropy is a layer of defense for the moment access control fails. Fails the unpredictability requirement.
Volatile ids (freshly generated per request) — opaque but not stable; they break lookup and deduplication for every receiver downstream. Fails the stability requirement.
A resource identified only by an id from a failing scheme can therefore be exchanged under empty mode only, not id-only.
Id Examples
Random, Keyed transformation, and Per-recipient are three constructions that satisfy the stability, opacity, and unpredictability requirements, each identifying the same internal resource, key 4711 in the source system's database — the values are illustrative. See Event Notification for the id from the Random example carried in an actual notification.
Any construction must also yield a valid FHIR id: at most 64 characters, drawn from A–Z, a–z, 0–9, "-" and "." (FHIR R4, id datatype). This excludes, for example, base64url encoding, which uses "_", and limits the length of the value that can be encoded.
Constructing an Id: Random (UUIDv4)
A randomly generated value, created once and stored with the resource. Because it's random rather than derived from anything, it reveals nothing about the resource's creation order, timing, or content. A UUIDv4 carries 122 random bits, well above the minimum of 64 bits, provided it is generated by a cryptographically secure random number generator.
Resulting id: 5f2f9a4e-8c1d-4b6e-9d3a-7c0e2f4b8a1d
Constructing an Id: Keyed Transformation (HMAC)
A value computed from the resource's internal reference using a keyed cryptographic transformation such as HMAC (RFC 2104 / FIPS 198-1), with a hash function and key length that are, at the time of implementation, considered secure (e.g. HMAC-SHA-256 or stronger). The same resource always produces the same id (stability). Without the secret key, the id cannot be linked to the source's internal reference, nor computed or confirmed from it (opacity and unpredictability), provided the output is at least 64 bits. The resulting id below is encoded as 24 characters from the RFC 4648 base32 alphabet in lower case, without padding: 120 bits.
These properties depend entirely on the secrecy of the key. The internal reference is typically low-entropy, such as a sequential database key, so anyone who obtains the key can compute the id of every resource. The construction holds only as long as the source keeps the key secret. Changing the key changes every id and thus breaks stability; replacing a key requires a transition for existing ids, which is outside the scope of this TA.
A keyed hash cannot be reversed, so the source resolves an incoming id by storing or indexing the computed id with the resource, as with a random id. The advantage of this construction is that the id can be recomputed from the internal reference, rather than having to be generated and stored first.
Source value: Task/4711 Resulting id: j5xw6z3vnfxgk4ttmvwgc3dj
Constructing an Id: Per-Recipient
A variant of the keyed transformation above, inheriting the same stability, opacity, and unpredictability properties, and the same dependence on the secrecy of the key from which the per-receiver keys are derived. Each receiver ends up with a different id for the same resource, so receivers can't link it across their separate views; the tradeoff is that only the source can tell the two ids refer to the same resource.
Source values: Task/4711 + URA 12104037 (receiver A) Resulting id (receiver A): k2mdpq7fbzxtc4qslmvwgy3e
Source values: Task/4711 + URA 54783291 (receiver B) Resulting id (receiver B): r6ntgh5xowzslb3cqfj47x2n
Per-recipient ids provide this protection only if they are applied consistently, which has consequences beyond the notification itself:
-
The protection holds only if the resource returned on retrieval carries the same per-recipient id in Resource.id; otherwise the receiver learns the shared id.
-
References inside the returned resource (e.g.
Task.for,Task.focus) disclose the ids of other resources. Unless those are per-recipient too, receivers can still link through them. In practice, per-recipient ids therefore amount to a per-recipient view of every resource the receiver can retrieve. -
The source must resolve an incoming per-recipient id to its internal resource, both on retrieval and on any update by the receiver. Since a keyed hash cannot be reversed, this requires either a stored mapping per receiver, or a reversible keyed construction such as deterministic authenticated encryption (e.g. AES-SIV, RFC 5297).
-
An id that the receiver passes on to a third party, for instance when care is handed over, does not resolve for that third party.
Whether these consequences are acceptable for a given exchange is part of the decision on broadly accessible resources (see When a Reference Is Preferable to Empty).
Changes since 0.9
-
Introduction. Conformance verbs defined: SHALL, SHALL NOT, SHOULD, SHOULD NOT and MAY are to be interpreted as in FHIR R4 (Conformance Rules, Conformance Language), only when in capitals. (editorial)
-
Throughout. MUST and MUST NOT replaced by SHALL and SHALL NOT, in line with the FHIR R4 conformance language; no obligation changes. (editorial)
-
Vocabulary. Added in-band/out-of-band and sender-initiated/receiver-initiated, and the distinction between them. (editorial)
-
Notification Payload Model, Privacy, Consent, and Authorization, Sequence Diagram, Requirements on Use-Case-Specific Technical Agreements. The resource in a full-resource notification need not be clinical content. The use-case-specific technical agreement states what data it contains; the content-specific processing-basis requirements apply only where that includes personal data, and the requirements that apply to empty and id-only notifications still do. A notified pull of resources referenced from it remains possible. (technical)
-
Notification Patterns, Sequence Diagram, Heartbeat Notification. “Source initiated” renamed to “sender-initiated”. (editorial)
-
Preconditions, Sequence Diagram, Replacing a Subscription, Requirements on Use-Case-Specific Technical Agreements. A Subscription whose SubscriptionTopic is no longer designated is set to off. Where a topic is succeeded by another, the use-case-specific technical agreement keeps both designated for a transition period, so that Subscriptions can be replaced. (technical)
-
Authorization for Pulls under Out-of-Band Subscriptions, Resource Definitions → Notification → Authorization value. Whether an authorization value may be carried now depends on out-of-band creation of the Subscription, not on the sender-initiated pattern. Section renamed from Authorization for Sender-Initiated Pulls. (technical)
-
Resource Definitions → Notification, Requirements on Use-Case-Specific Technical Agreements. related-query, following the Backport IG 1.2.0 ballot, is not permitted in empty mode, and in id-only and full-resource mode only where the use-case-specific technical agreement permits it; a query contains no real-world identifying numbers. (technical)
-
Event Notification. Removed the rule that a notification carries no content beyond what the payload mode permits; this already follows from Payload Mode Agreement and Enforcement. (editorial)
-
Requirements on Use-Case-Specific Technical Agreements, Appendix A → Constructing an Id: Per-Recipient. Where per-recipient ids are used, the use-case-specific technical agreement states how retrieval returns the resource under the same per-recipient id, and how references to other resources within it are handled. The appendix, being informative, no longer states this as a requirement. (technical)
-
Appendix A → Constructing an Id: Keyed Transformation (HMAC), Schemes That Fail. Rephrased without normative wording; requirements follow from Requirements for Using Id-Only. (editorial)