This page is part of the FHIR Specification (v5.0.0-snapshot3: R5 Snapshot #3, to support Connectathon 32). The current version which supercedes this version is 5.0.0. For a full list of available versions, see the Directory of published versions . Page versions: R5 R4B R4 R3 R2
FHIR Infrastructure Work Group | Maturity Level: 2 | Trial Use | Security Category: Business | Compartments: Not linked to any defined compartments |
The subscription resource describes a particular client's request to be notified about a SubscriptionTopic.
This document contains information about the Subscription
resource and details specific to options in it. See Subscriptions for general information about using Subscriptions in FHIR.
The Subscription
resource is used to establish proactive event notifications from a FHIR server to another system. Subscribers request event notifications within a predefined SubscriptionTopic that the server supports, and can further refine their notifications by supplying filters. Each SubscriptionTopic
resource defines a set of allowed filters (SubscriptionTopic.canFilterBy
), which a subscriber refer to within a Subscription
resource (Subscription.filterBy
). Once a subscription is created, any event matching a specified SubscriptionTopic that meets the filtering criteria will cause a notification to be sent using the provided channel. Notifications are Bundle resources, of type subscription-notification
.
Subscriptions are active resources; a server can only accept a subscription if it will execute the specified channel for any resources subsequently received. The subscription is no longer active once it is deleted from the server.
By adjusting Subscription.content
, subscribers can request event notifications that include full resource content; or just the ID of the triggering resource; or an empty notification body.
Several channels are defined in the core specification:
Subscription.endpoint
URL (e.g., https://...
)Subscription.endpoint
email URI (e.g., mailto:...
)Subscription.endpoint
URIAdditional channel types can be defined by external implementation guides. See below for further discussion of the various channels.
The Subscription
resource is used in the Subscriptions Framework. Information about the Boundaries and Relationships both within the Subscriptions Framework and to other areas of the FHIR specification can be found here.
Structure
Name | Flags | Card. | Type | Description & Constraints |
---|---|---|---|---|
Subscription | TU | DomainResource | Notification about a SubscriptionTopic Elements defined in Ancestors: id, meta, implicitRules, language, text, contained, extension, modifierExtension | |
identifier | Σ | 0..* | Identifier | Additional identifiers (business identifier) |
name | Σ | 0..1 | string | Human readable name for this subscription |
status | ?!Σ | 1..1 | code | requested | active | error | off | entered-in-error Subscription Status (Required) |
topic | Σ | 1..1 | canonical(SubscriptionTopic) | Reference to the subscription topic being subscribed to |
contact | Σ | 0..* | ContactPoint | Contact details for source (e.g. troubleshooting) |
end | Σ | 0..1 | instant | When to automatically delete the subscription |
managingEntity | Σ | 0..1 | Reference(CareTeam | HealthcareService | Organization | RelatedPerson | Patient | Practitioner | PractitionerRole) | Entity responsible for Subscription changes |
reason | Σ | 0..1 | string | Description of why this subscription was created |
filterBy | Σ | 0..* | BackboneElement | Criteria for narrowing the subscription topic stream |
resourceType | Σ | 0..1 | uri | Allowed Data type or Resource (reference to definition) for this Subscription All FHIR Types (Extensible) |
filterParameter | Σ | 1..1 | string | Filter label defined in SubscriptionTopic |
modifier | Σ | 0..1 | code | = | eq | ne | gt | lt | ge | le | sa | eb | ap | above | below | in | not-in | of-type Subscription Search Modifier (Required) |
value | Σ | 1..1 | string | Literal value or resource path |
channelType | Σ | 1..1 | Coding | Channel type for notifications Subscription Channel Type (Extensible) |
endpoint | Σ | 0..1 | url | Where the channel points to |
header | Σ | 0..* | string | Usage depends on the channel type |
heartbeatPeriod | Σ | 0..1 | unsignedInt | Interval in seconds to send 'heartbeat' notification |
timeout | Σ | 0..1 | unsignedInt | Timeout in seconds to attempt notification delivery |
contentType | Σ | 0..1 | code | MIME type to send, or omit for no payload Mime Types (Required) |
content | Σ | 0..1 | code | empty | id-only | full-resource SubscriptionPayloadContent (Required) |
maxCount | Σ | 0..1 | positiveInt | Maximum number of triggering resources included in notification bundles |
Documentation for this format |
See the Extensions for this resource
UML Diagram (Legend)
XML Template
<Subscription xmlns="http://hl7.org/fhir"> <!-- from Resource: id, meta, implicitRules, and language --> <!-- from DomainResource: text, contained, extension, and modifierExtension --> <identifier><!-- 0..* Identifier Additional identifiers (business identifier) --></identifier> <name value="[string]"/><!-- 0..1 Human readable name for this subscription --> <status value="[code]"/><!-- 1..1 requested | active | error | off | entered-in-error --> <topic><!-- 1..1 canonical(SubscriptionTopic) Reference to the subscription topic being subscribed to --></topic> <contact><!-- 0..* ContactPoint Contact details for source (e.g. troubleshooting) --></contact> <end value="[instant]"/><!-- 0..1 When to automatically delete the subscription --> <managingEntity><!-- 0..1 Reference(CareTeam|HealthcareService|Organization| Patient|Practitioner|PractitionerRole|RelatedPerson) Entity responsible for Subscription changes --></managingEntity> <reason value="[string]"/><!-- 0..1 Description of why this subscription was created --> <filterBy> <!-- 0..* Criteria for narrowing the subscription topic stream --> <resourceType value="[uri]"/><!-- 0..1 Allowed Data type or Resource (reference to definition) for this Subscription --> <filterParameter value="[string]"/><!-- 1..1 Filter label defined in SubscriptionTopic --> <modifier value="[code]"/><!-- 0..1 = | eq | ne | gt | lt | ge | le | sa | eb | ap | above | below | in | not-in | of-type --> <value value="[string]"/><!-- 1..1 Literal value or resource path --> </filterBy> <channelType><!-- 1..1 Coding Channel type for notifications --></channelType> <endpoint value="[url]"/><!-- 0..1 Where the channel points to --> <header value="[string]"/><!-- 0..* Usage depends on the channel type --> <heartbeatPeriod value="[unsignedInt]"/><!-- 0..1 Interval in seconds to send 'heartbeat' notification --> <timeout value="[unsignedInt]"/><!-- 0..1 Timeout in seconds to attempt notification delivery --> <contentType value="[code]"/><!-- 0..1 MIME type to send, or omit for no payload --> <content value="[code]"/><!-- 0..1 empty | id-only | full-resource --> <maxCount value="[positiveInt]"/><!-- 0..1 Maximum number of triggering resources included in notification bundles --> </Subscription>
JSON Template
{ "resourceType" : "Subscription", // from Resource: id, meta, implicitRules, and language // from DomainResource: text, contained, extension, and modifierExtension "identifier" : [{ Identifier }], // Additional identifiers (business identifier) "name" : "<string>", // Human readable name for this subscription "status" : "<code>", // R! requested | active | error | off | entered-in-error "topic" : "<canonical(SubscriptionTopic)>", // R! Reference to the subscription topic being subscribed to "contact" : [{ ContactPoint }], // Contact details for source (e.g. troubleshooting) "end" : "<instant>", // When to automatically delete the subscription "managingEntity" : { Reference(CareTeam|HealthcareService|Organization| Patient|Practitioner|PractitionerRole|RelatedPerson) }, // Entity responsible for Subscription changes "reason" : "<string>", // Description of why this subscription was created "filterBy" : [{ // Criteria for narrowing the subscription topic stream "resourceType" : "<uri>", // Allowed Data type or Resource (reference to definition) for this Subscription "filterParameter" : "<string>", // R! Filter label defined in SubscriptionTopic "modifier" : "<code>", // = | eq | ne | gt | lt | ge | le | sa | eb | ap | above | below | in | not-in | of-type "value" : "<string>" // R! Literal value or resource path }], "channelType" : { Coding }, // R! Channel type for notifications "endpoint" : "<url>", // Where the channel points to "header" : ["<string>"], // Usage depends on the channel type "heartbeatPeriod" : "<unsignedInt>", // Interval in seconds to send 'heartbeat' notification "timeout" : "<unsignedInt>", // Timeout in seconds to attempt notification delivery "contentType" : "<code>", // MIME type to send, or omit for no payload "content" : "<code>", // empty | id-only | full-resource "maxCount" : "<positiveInt>" // Maximum number of triggering resources included in notification bundles }
Turtle Template
@prefix fhir: <http://hl7.org/fhir/> . [ a fhir:Subscription; fhir:nodeRole fhir:treeRoot; # if this is the parser root # from Resource: .id, .meta, .implicitRules, and .language # from DomainResource: .text, .contained, .extension, and .modifierExtension fhir:Subscription.identifier [ Identifier ], ... ; # 0..* Additional identifiers (business identifier) fhir:Subscription.name [ string ]; # 0..1 Human readable name for this subscription fhir:Subscription.status [ code ]; # 1..1 requested | active | error | off | entered-in-error fhir:Subscription.topic [ canonical(SubscriptionTopic) ]; # 1..1 Reference to the subscription topic being subscribed to fhir:Subscription.contact [ ContactPoint ], ... ; # 0..* Contact details for source (e.g. troubleshooting) fhir:Subscription.end [ instant ]; # 0..1 When to automatically delete the subscription fhir:Subscription.managingEntity [ Reference(CareTeam|HealthcareService|Organization|Patient|Practitioner|PractitionerRole| RelatedPerson) ]; # 0..1 Entity responsible for Subscription changes fhir:Subscription.reason [ string ]; # 0..1 Description of why this subscription was created fhir:Subscription.filterBy [ # 0..* Criteria for narrowing the subscription topic stream fhir:Subscription.filterBy.resourceType [ uri ]; # 0..1 Allowed Data type or Resource (reference to definition) for this Subscription fhir:Subscription.filterBy.filterParameter [ string ]; # 1..1 Filter label defined in SubscriptionTopic fhir:Subscription.filterBy.modifier [ code ]; # 0..1 = | eq | ne | gt | lt | ge | le | sa | eb | ap | above | below | in | not-in | of-type fhir:Subscription.filterBy.value [ string ]; # 1..1 Literal value or resource path ], ...; fhir:Subscription.channelType [ Coding ]; # 1..1 Channel type for notifications fhir:Subscription.endpoint [ url ]; # 0..1 Where the channel points to fhir:Subscription.header [ string ], ... ; # 0..* Usage depends on the channel type fhir:Subscription.heartbeatPeriod [ unsignedInt ]; # 0..1 Interval in seconds to send 'heartbeat' notification fhir:Subscription.timeout [ unsignedInt ]; # 0..1 Timeout in seconds to attempt notification delivery fhir:Subscription.contentType [ code ]; # 0..1 MIME type to send, or omit for no payload fhir:Subscription.content [ code ]; # 0..1 empty | id-only | full-resource fhir:Subscription.maxCount [ positiveInt ]; # 0..1 Maximum number of triggering resources included in notification bundles ]
Changes since R4
Subscription | |
Subscription.identifier |
|
Subscription.name |
|
Subscription.topic |
|
Subscription.managingEntity |
|
Subscription.reason |
|
Subscription.filterBy |
|
Subscription.filterBy.resourceType |
|
Subscription.filterBy.filterParameter |
|
Subscription.filterBy.modifier |
|
Subscription.filterBy.value |
|
Subscription.channelType |
|
Subscription.endpoint |
|
Subscription.header |
|
Subscription.heartbeatPeriod |
|
Subscription.timeout |
|
Subscription.contentType |
|
Subscription.content |
|
Subscription.maxCount |
|
Subscription.criteria |
|
Subscription.error |
|
Subscription.channel |
|
See the Full Difference for further information
This analysis is available as XML or JSON.
See R3 <--> R4 Conversion Maps (status = 2 tests that all execute ok. 2 fail round-trip testing and all r3 resources are valid.)
Structure
Name | Flags | Card. | Type | Description & Constraints |
---|---|---|---|---|
Subscription | TU | DomainResource | Notification about a SubscriptionTopic Elements defined in Ancestors: id, meta, implicitRules, language, text, contained, extension, modifierExtension | |
identifier | Σ | 0..* | Identifier | Additional identifiers (business identifier) |
name | Σ | 0..1 | string | Human readable name for this subscription |
status | ?!Σ | 1..1 | code | requested | active | error | off | entered-in-error Subscription Status (Required) |
topic | Σ | 1..1 | canonical(SubscriptionTopic) | Reference to the subscription topic being subscribed to |
contact | Σ | 0..* | ContactPoint | Contact details for source (e.g. troubleshooting) |
end | Σ | 0..1 | instant | When to automatically delete the subscription |
managingEntity | Σ | 0..1 | Reference(CareTeam | HealthcareService | Organization | RelatedPerson | Patient | Practitioner | PractitionerRole) | Entity responsible for Subscription changes |
reason | Σ | 0..1 | string | Description of why this subscription was created |
filterBy | Σ | 0..* | BackboneElement | Criteria for narrowing the subscription topic stream |
resourceType | Σ | 0..1 | uri | Allowed Data type or Resource (reference to definition) for this Subscription All FHIR Types (Extensible) |
filterParameter | Σ | 1..1 | string | Filter label defined in SubscriptionTopic |
modifier | Σ | 0..1 | code | = | eq | ne | gt | lt | ge | le | sa | eb | ap | above | below | in | not-in | of-type Subscription Search Modifier (Required) |
value | Σ | 1..1 | string | Literal value or resource path |
channelType | Σ | 1..1 | Coding | Channel type for notifications Subscription Channel Type (Extensible) |
endpoint | Σ | 0..1 | url | Where the channel points to |
header | Σ | 0..* | string | Usage depends on the channel type |
heartbeatPeriod | Σ | 0..1 | unsignedInt | Interval in seconds to send 'heartbeat' notification |
timeout | Σ | 0..1 | unsignedInt | Timeout in seconds to attempt notification delivery |
contentType | Σ | 0..1 | code | MIME type to send, or omit for no payload Mime Types (Required) |
content | Σ | 0..1 | code | empty | id-only | full-resource SubscriptionPayloadContent (Required) |
maxCount | Σ | 0..1 | positiveInt | Maximum number of triggering resources included in notification bundles |
Documentation for this format |
See the Extensions for this resource
XML Template
<Subscription xmlns="http://hl7.org/fhir"> <!-- from Resource: id, meta, implicitRules, and language --> <!-- from DomainResource: text, contained, extension, and modifierExtension --> <identifier><!-- 0..* Identifier Additional identifiers (business identifier) --></identifier> <name value="[string]"/><!-- 0..1 Human readable name for this subscription --> <status value="[code]"/><!-- 1..1 requested | active | error | off | entered-in-error --> <topic><!-- 1..1 canonical(SubscriptionTopic) Reference to the subscription topic being subscribed to --></topic> <contact><!-- 0..* ContactPoint Contact details for source (e.g. troubleshooting) --></contact> <end value="[instant]"/><!-- 0..1 When to automatically delete the subscription --> <managingEntity><!-- 0..1 Reference(CareTeam|HealthcareService|Organization| Patient|Practitioner|PractitionerRole|RelatedPerson) Entity responsible for Subscription changes --></managingEntity> <reason value="[string]"/><!-- 0..1 Description of why this subscription was created --> <filterBy> <!-- 0..* Criteria for narrowing the subscription topic stream --> <resourceType value="[uri]"/><!-- 0..1 Allowed Data type or Resource (reference to definition) for this Subscription --> <filterParameter value="[string]"/><!-- 1..1 Filter label defined in SubscriptionTopic --> <modifier value="[code]"/><!-- 0..1 = | eq | ne | gt | lt | ge | le | sa | eb | ap | above | below | in | not-in | of-type --> <value value="[string]"/><!-- 1..1 Literal value or resource path --> </filterBy> <channelType><!-- 1..1 Coding Channel type for notifications --></channelType> <endpoint value="[url]"/><!-- 0..1 Where the channel points to --> <header value="[string]"/><!-- 0..* Usage depends on the channel type --> <heartbeatPeriod value="[unsignedInt]"/><!-- 0..1 Interval in seconds to send 'heartbeat' notification --> <timeout value="[unsignedInt]"/><!-- 0..1 Timeout in seconds to attempt notification delivery --> <contentType value="[code]"/><!-- 0..1 MIME type to send, or omit for no payload --> <content value="[code]"/><!-- 0..1 empty | id-only | full-resource --> <maxCount value="[positiveInt]"/><!-- 0..1 Maximum number of triggering resources included in notification bundles --> </Subscription>
JSON Template
{ "resourceType" : "Subscription", // from Resource: id, meta, implicitRules, and language // from DomainResource: text, contained, extension, and modifierExtension "identifier" : [{ Identifier }], // Additional identifiers (business identifier) "name" : "<string>", // Human readable name for this subscription "status" : "<code>", // R! requested | active | error | off | entered-in-error "topic" : "<canonical(SubscriptionTopic)>", // R! Reference to the subscription topic being subscribed to "contact" : [{ ContactPoint }], // Contact details for source (e.g. troubleshooting) "end" : "<instant>", // When to automatically delete the subscription "managingEntity" : { Reference(CareTeam|HealthcareService|Organization| Patient|Practitioner|PractitionerRole|RelatedPerson) }, // Entity responsible for Subscription changes "reason" : "<string>", // Description of why this subscription was created "filterBy" : [{ // Criteria for narrowing the subscription topic stream "resourceType" : "<uri>", // Allowed Data type or Resource (reference to definition) for this Subscription "filterParameter" : "<string>", // R! Filter label defined in SubscriptionTopic "modifier" : "<code>", // = | eq | ne | gt | lt | ge | le | sa | eb | ap | above | below | in | not-in | of-type "value" : "<string>" // R! Literal value or resource path }], "channelType" : { Coding }, // R! Channel type for notifications "endpoint" : "<url>", // Where the channel points to "header" : ["<string>"], // Usage depends on the channel type "heartbeatPeriod" : "<unsignedInt>", // Interval in seconds to send 'heartbeat' notification "timeout" : "<unsignedInt>", // Timeout in seconds to attempt notification delivery "contentType" : "<code>", // MIME type to send, or omit for no payload "content" : "<code>", // empty | id-only | full-resource "maxCount" : "<positiveInt>" // Maximum number of triggering resources included in notification bundles }
Turtle Template
@prefix fhir: <http://hl7.org/fhir/> . [ a fhir:Subscription; fhir:nodeRole fhir:treeRoot; # if this is the parser root # from Resource: .id, .meta, .implicitRules, and .language # from DomainResource: .text, .contained, .extension, and .modifierExtension fhir:Subscription.identifier [ Identifier ], ... ; # 0..* Additional identifiers (business identifier) fhir:Subscription.name [ string ]; # 0..1 Human readable name for this subscription fhir:Subscription.status [ code ]; # 1..1 requested | active | error | off | entered-in-error fhir:Subscription.topic [ canonical(SubscriptionTopic) ]; # 1..1 Reference to the subscription topic being subscribed to fhir:Subscription.contact [ ContactPoint ], ... ; # 0..* Contact details for source (e.g. troubleshooting) fhir:Subscription.end [ instant ]; # 0..1 When to automatically delete the subscription fhir:Subscription.managingEntity [ Reference(CareTeam|HealthcareService|Organization|Patient|Practitioner|PractitionerRole| RelatedPerson) ]; # 0..1 Entity responsible for Subscription changes fhir:Subscription.reason [ string ]; # 0..1 Description of why this subscription was created fhir:Subscription.filterBy [ # 0..* Criteria for narrowing the subscription topic stream fhir:Subscription.filterBy.resourceType [ uri ]; # 0..1 Allowed Data type or Resource (reference to definition) for this Subscription fhir:Subscription.filterBy.filterParameter [ string ]; # 1..1 Filter label defined in SubscriptionTopic fhir:Subscription.filterBy.modifier [ code ]; # 0..1 = | eq | ne | gt | lt | ge | le | sa | eb | ap | above | below | in | not-in | of-type fhir:Subscription.filterBy.value [ string ]; # 1..1 Literal value or resource path ], ...; fhir:Subscription.channelType [ Coding ]; # 1..1 Channel type for notifications fhir:Subscription.endpoint [ url ]; # 0..1 Where the channel points to fhir:Subscription.header [ string ], ... ; # 0..* Usage depends on the channel type fhir:Subscription.heartbeatPeriod [ unsignedInt ]; # 0..1 Interval in seconds to send 'heartbeat' notification fhir:Subscription.timeout [ unsignedInt ]; # 0..1 Timeout in seconds to attempt notification delivery fhir:Subscription.contentType [ code ]; # 0..1 MIME type to send, or omit for no payload fhir:Subscription.content [ code ]; # 0..1 empty | id-only | full-resource fhir:Subscription.maxCount [ positiveInt ]; # 0..1 Maximum number of triggering resources included in notification bundles ]
Changes since Release 4
Subscription | |
Subscription.identifier |
|
Subscription.name |
|
Subscription.topic |
|
Subscription.managingEntity |
|
Subscription.reason |
|
Subscription.filterBy |
|
Subscription.filterBy.resourceType |
|
Subscription.filterBy.filterParameter |
|
Subscription.filterBy.modifier |
|
Subscription.filterBy.value |
|
Subscription.channelType |
|
Subscription.endpoint |
|
Subscription.header |
|
Subscription.heartbeatPeriod |
|
Subscription.timeout |
|
Subscription.contentType |
|
Subscription.content |
|
Subscription.maxCount |
|
Subscription.criteria |
|
Subscription.error |
|
Subscription.channel |
|
See the Full Difference for further information
This analysis is available as XML or JSON.
See R3 <--> R4 Conversion Maps (status = 2 tests that all execute ok. 2 fail round-trip testing and all r3 resources are valid.)
Additional definitions: Master Definition XML + JSON, XML Schema/Schematron + JSON Schema, ShEx (for Turtle) + see the extensions, the spreadsheet version & the dependency analysis
Path | Definition | Type | Reference |
---|---|---|---|
Subscription.status | State values for FHIR Subscriptions. | Required | SubscriptionStatusCodes (a valid code from SubscriptionStatus) |
Subscription.filterBy.resourceType | All FHIR types | Extensible | FHIRTypes (a valid code from All FHIR Types) |
Subscription.filterBy.modifier | FHIR search modifiers allowed for use in Subscriptions and SubscriptionTopics. | Required | SubscriptionSearchModifier (a valid code from SubscriptionSearchModifer) |
Subscription.channelType | Core-defined FHIR channel types allowed for use in Subscriptions. | Extensible | SubscriptionChannelType (a valid code from SubscriptionChannel Type Codes ) |
Subscription.contentType | This value set includes all possible codes from BCP-13 (http://tools.ietf.org/html/bcp13) | Required | MimeTypes (a valid code from urn:ietf:bcp:13 ) |
Subscription.content | Codes to represent how much resource content to send in the notification payload. | Required | SubscriptionPayloadContent |
Applications are responsible for following FHIR security guidance. Some recommendations specific to subscriptions are provided on the Subscriptions Framework page.
There are three options available when specifying the contents of a Notification: empty
, id-only
, and full-resource
. These options change the level of detail conveyed in the notification Bundle
.
When deciding which payload type to request, systems SHOULD consider both ease of processing and security of PHI. To mitigate the risk of information leakage, systems SHOULD use the minimum level of detail consistent with the use case. In practice, id-only
provides a good balance between security and performance for many real-world scenarios.
If a server cannot or will not honor a payload type (e.g., will not send full-resource
over HTTP), it SHOULD reject the Subscription request. A server MAY instead accept the subscription with modifications and return the accepted version to the client.
When sending event notifications servers SHALL populate the SubscriptionStatus.notificationEvent structure with relevant information, depending on the payload type.
An example notification with an empty
payload can be found here.
With the content type of empty
, all information about the resources involved in triggering the notification is only available via channels other than the Subscription itself (e.g., the REST API or $events operation). This mitigates many security concerns by both removing most PHI from the notification and allows servers to consolidate authorization and authentication logic. When the subscriber receives a notification of this type, it may query the server to fetch all the relevant resources based on the SubscriptionTopic
and applicable filters. The client might include a _lastUpdated
query parameter, supplying its last query timestamp to retrieve only the most recent resources. For example, if the notification is for a topic about patient admission, the subscriber will generally query for recent Encounters for a patient or group of patients, then fetch them as needed.
When populating the SubscriptionStatus.notificationEvent
structure for a notification with an empty
payload, a server SHALL NOT include references to resources (e.g., SubscriptionStatus.notificationEvent.focus and SubscriptionStatus.notificationEvent.additionalContext SHALL NOT be present).
When the content type is empty
, notification bundles SHALL NOT contain Bundle.entry
elements other than the SubscriptionStatus
for the notification.
An example notification with an id-only
payload can be found here.
With the content type of id-only
, the resources involved in triggering the notification are only available through other channels (e.g., REST API), but notifications include URLs which can be used to access those resources. This allows servers to consolidate authorization and authentication logic, while removing the need for expensive queries by subscribers. When a subscriber receives a notification of this type, it may directly fetch all the relevant resources using the supplied resource ids. For example, if the notification is for a topic about patient admission, the subscriber may fetch the Encounter(s) for a patient or group of patients.
When the content type is id-only
, the SubscriptionStatus.notificationEvent
structure SHALL include references to the appropriate focus resources in the SubscriptionStatus.notificationEvent.focus element. This provides clients a fixed location to consolidate IDs for all notification types.
Additionally, notification bundles MAY contain, in addition to the SubscriptionStatus
, at least one Bundle.entry
for each resource relevant to the notification. For example, a notification for a topic based on Encounter MAY include a reference to the Encounter and MAY also include additional resources deemed relevant (e.g., the linked Patient).
An example notification with a full-resource
payload can be found here.
With the content type of full-resource
, the resources involved in triggering the notification are included in the notification bundle. When a subscriber receives a notification of this type, resources are already present in the bundle, though the subscriber may need to fetch additional resources from the server. For example, the if the notification is for a topic about patient admission, the subscriber may require related Observation
resources.
When the content type is full-resource
, the SubscriptionStatus.notificationEvent
structure SHALL include references to the appropriate focus resources in the SubscriptionStatus.notificationEvent.focus element. This provides clients a fixed location to consolidate IDs for all notification types.
Notification bundles for full-resource
subscriptions SHALL contain, in addition to the SubscriptionStatus
, at least one Bundle.entry
for each resource relevant to the notification. For example, a notification for a topic based on Encounter SHALL include an Encounter and MAY include additional resources deemed relevant (e.g., the relevant Patient). Each Bundle.entry
for a full-resource
notification SHALL contain a relevant resource in the entry.resource
element. If a server cannot include the resource contents due to an issue with a specific notification, the server SHALL populate the entry.request
and/or entry.response
elements.
This specification defines a core set of channel types to cover the majority of common use cases. Servers MAY define additional channel types as needed. Below is some guidance for implementers to consider when selecting a channel type.
The FHIR standard makes extensive use of the RESTful model. Given the popularity of REST and widespread adoption, most implementers should consider using REST-hook channels whenever possible. In general, REST-based systems are well-supported (e.g., tooling, infrastructure, documentation, etc.), and will present the lowest bar for implementation.
Websockets are unique in the pre-defined channel types in being the only channel that does not require the client to have an endpoint. Due to this property, the websocket channel is very useful for clients where creating an endpoint would be difficult or impossible (e.g., mobile clients, web-based clients, etc.).
The Email channel is the only channel that could contest REST in non-FHIR implementations. That said, Email communication is often high-latency and is typically used for communication to individuals - not applications. Email channels are particularly useful in the context of these non-application use cases, such as public health notifications. For example, if a public health agency does not have the ability or desire to build a custom RESTful solution (e.g., creating and maintaining an endpoint to receive notifications, as well as software to consume those notifications), it is straightforward to map notifications to email addresses or aliases.
FHIR Messaging is a mechanism defined to allow for non-RESTful communication between FHIR servers and clients. One common use case is when connectivity is an issue (e.g., remote sites that batch all communications when connections are available). This channel defines how to integrate topic-based subscriptions with the FHIR Messaging model.
For use cases that are not well-met by any of the predefined channels, the Subscriptions Framework allows for custom channel definitions. Some examples of scenarios where custom channels may be applicable include:
To receive notifications via HTTP/S POST, a client requests a subscription with the channel type of `rest-hook` (from the subscription-channel-type
Code System) and and an endpoint (Subscription.endpoint
) with the desired URL. Note that this URL must be accessible by the hosting server.
To convey an event notification, the server POSTs a notification Bundle
to the client's nominated endpoint URL per the format requests in the Subscription:
content-type
of the POST SHALL match the MIME type on the Subscription Subscription.contentType.
When a subscription is created for a REST Hook channel type, the server SHALL set initial status to requested
, pending verification of the nominated endpoint URL. After a successful handshake
notification has been sent and accepted, the server SHALL update the status to active
. Any errors in the initial handshake
SHALL result in the status being changed to error
.
An example workflow for establishing a rest-hook
subscription is shown below.
Subscription
with the channelType
set to rest-hook
.
requested
.
handshake
notification.
200
).
heartbeat
at any time (SHOULD at least once per heartbeatPeriod
).
heartbeat
via HTTP POST and returns an HTTP success code (e.g., 200
).
event-notification
when triggered.
event-notification
via HTTP POST and returns an HTTP code (e.g., 200
).
HTTP is neither a secure nor an encrypted channel, nor does it provide endpoint verification. It is strongly recommended that implementations refuse requests to send notifications to URLs using the HTTP protocol (use HTTPS instead).
While the primary interface for FHIR servers is the FHIR REST API, notifications need not occur via REST. Indeed, some subscribers may be unable to expose an outward-facing HTTP server to receive triggered notifications. For example, a pure client-side Web app or mobile app may want to subscribe to a data feed. This can be accomplished using a websocket
notification channel from the subscription-channel-type
Code System.
To receive notifications via WebSocket, a client requests a subscription with the channel type (Subscription.channelType
) of websocket
(from the subscription-channel-type Code System). Note that no endpoint (Subscription.endpoint
) is used in websocket channels, since clients connect to a server-hosted websocket URL.
An example workflow for receiving notifications via websockets is shown below:
Subscription
with the channelType
set to websocket
.
token
, expiration
, and websocket-url
.
websocket-url
(wss://
preferred).
bind-with-token
message via websockets, with the token provided by the server. Note: this operation can be repeated concurrently for multiple subscriptions that share the same websocket-url
, and serially for continued operation over a single websocket connection.
handshake
messages via websockets (one per Subscription included in the token). Note: some servers may additionally send one or more event-notification
messages at this time (e.g., all messages since last connected, last 'n' messages, etc.). Clients are expected to handle either flow.
heartbeat
at any time (SHOULD at least once per heartbeatPeriod
).
event-notification
when triggered.
$get-ws-binding-token
operation via REST.
token
, expiration
, and websocket-url
. Note that the token
and websocket-url
MAY be the same or new values, as determined by the server.
websocket-url
is different from the existing connection, the Client establishes a new connection to the Client Endpoint.
bind-with-token
message via websockets, with the token provided by the server. Note: this operation can be repeated concurrently for multiple subscriptions that return the same websocket-url
, and serially for continued operation over a single websocket connection.
handshake
messages via websockets (one per Subscription included in the token). Note: some servers may additionally send one or more event-notification
messages at this time (e.g., all messages since last connected, last 'n' messages, etc.). Clients are expected to handle either flow.
Notes:
Note to Implementers: The Websocket channel type needs more testing and feedback to ensure all requirements are met before finalizing the specification.
WebSocket security poses several challenges specific to the channel. When implementing websockets for notifications, please keep in mind the following list of some areas of concern:
While the primary interface for FHIR servers is the FHIR REST API, notifications need not occur via REST. Indeed, some subscribers may be unable to maintain an outward-facing HTTP server to receive triggered notifications. For example, a public health organization may want to be notified of outbreaks of various illnesses. This can be accomplished using an email
notification channel.
To receive notifications via Email, a client requests a subscription with the channel type (Subscription.channelType
) of email
(from the subscription-channel-type Code System) and an endpoint (Subscription.endpoint
) with the desired email URI (e.g., mailto:public_health_notifications@example.org
).
The server will send a new message each time a notification should be sent (e.g., per event or per batch). The server will create a message based on the values present in the Subscription.contentType
and Subscription.content
fields. If a server cannot honor the requested combination, the server should reject the Subscription request rather than send unexpected email messages.
The email channel sets two guidelines about content:
Due to these guidelines, the Subscription.contentType
refers to the content of the body of the message. Attachment type information can be appended as a MIME parameter, for example:
text/plain
: a plain-text body with no attachmenttext/html
: an HTML body with no attachmenttext/plain;attach=application/fhir+json
: a plain-text body with a FHIR JSON bundle attachedtext/html;attach=application/fhir+xml
: an HTML body with a FHIR XML bundle attached
The Subscription.content
field SHALL be applied to any attachments, and MAY be applied to body contents (depending on server implementation). However, a server must not include a body which exceeds the specified content level. For example, a server may choose to always include a standard message in the body of the message containing no PHI and vary the attachment, but cannot include PHI in the body of an email when the content is set to empty
.
An example workflow using the email
channel type is included below.
Subscription
with the channelType
set to email
.
active
.
requested
.
250: OK
).
heartbeat
at any time (SHOULD at least once per heartbeatPeriod
).
event-notification
at any time.
Email (SMTP) is not a secure channel. Implementers must ensure that any messages containing PHI have been secured according to their policy requirements (e.g., use of a system such as Direct ).
There are times when it is desireable to use Subscriptions as a communication channel between FHIR servers that are connected via Messaging instead of REST. This can be accomplished using a Subscription
with the channel type of message
.
To receive notifications via messaging, a client should request a subscription with the channel type (Subscription.channelType
) of message
and set the endpoint (Subscription.endpoint
) to the destination FHIR server base URL. Note that this URL must be accessible by the hosting server.
The FHIR server hosting the subscription (server) will send FHIR messages to the destination FHIR server (endpoint) as needed. These messages will, as the contents of the message, have a fully-formed subscription-notification
Bundle. An example message can be found here.
An example workflow using the message
channel type is included below.
Subscription
with the channelType
set to message
.
requested
.
handshake
notification.
heartbeat
at any time (SHOULD at least once per heartbeatPeriod
).
event-notification
at any time.
Note to Implementers: The Messaging channel type needs more testing and feedback to ensure all requirements are met before finalizing the specification.
Servers MAY require that the end-point is white-listed prior to allowing these kinds of subscriptions. Additionally, servers MAY impose authorization/authentication requirements for server to server communication (e.g., certificate pinning, etc.).
Defining a new channel type requires clear communication to implementers of both clients and servers around requirements and expectations. Below are some areas which should be considered when creating a channel. Anyone defining a channel type is encouraged to publish their definition at registry.fhir.org .
Note to Implementers: Warning: This section is still in early drafting; feedback from topic authors is welcome to refine the following guidance.
At a minimum, the following items should be defined:
Subscription.channelType
(e.g., 'secure-mq' instead of 'channel0012')Subscription.endpoint
(e.g., URI, etc.)Subscription.header
field values (e.g., REST-hook defines as Auth headers included in a POST)Subscription.contentType
(e.g., email defines this as the email body, with allowable attachments.)handshake
notifications are used, and guidance on usage if they areheartbeat
notifications are used, and guidance on timings if they areDefining a channel has security implications. While it is not expected that authors cover all aspects of security, guidance specific to the channel SHOULD be provided. For example, when discussing REST-hooks, this specification includes guidance about using HTTPS over HTTP.
If the channel CANNOT be secured, that should be stated with a warning not to transfer PHI. If the channel is or can be secured, guidance should be given on how configurations relate to PHI safety, for example:
The subscription resource is authored by the client with an initial status of requested
. A new subscription is created on the server using the RESTful create or update interaction. After a successful transaction, the client parses the Location header and saves the new Subscription's logical id for use in subsequent operations.
When the server receives a subscription, it SHOULD check that it is prepared to accept/process the subscription. If it is, it sets the subscription to requested
and process it like a normal create. If it isn't, it SHOULD return an error with an OperationOutcome instead of processing the create
.
The criteria are subject to the same limitations as the client that created it, such as access to patient compartments etc. Note that the subscription MAY remain active after the client access tokens expire.
Once the server has activated the subscription, it sets the status to active
(note: the server may do this as it accepts the resource if it wants).
An appropriately authorized client can use search and/or history operations to see what subscriptions are currently active on the server. Once the subscription is no longer desired, the client deletes the subscription from the server.
The server may retry the notification a fixed number of times and/or refer errors to its own alert logs. If the notification fails, the server SHOULD set the status to error
and mark the error in the resource. If the notification succeeds, the server SHOULD update the status to active
and may remove any error codes. If a subscription fails consistently a server may choose set the subscription status to off
and stop trying to send notifications.
Errors a server wishes to make accessible to clients are stored in Subscription.error
. Servers should provide a mechanism for clearing errors (e.g., when resetting a Subscription.status
back to requested
after an error). Since Subscription.error
represents errors that a server has experienced, a server SHOULD NOT allow clients to add errors.
Search parameters for this resource. The common parameters also apply. See Searching for more information about searching in REST, messaging, and services.
Name | Type | Description | Expression | In Common |
contact | token | Contact details for the subscription | Subscription.contact | |
identifier | token | A subscription identifier | Subscription.identifier | |
payload | token | The mime-type of the notification payload | ||
status | token | The current state of the subscription | Subscription.status | |
type | token | The type of channel for the sent notifications | ||
url | uri | The uri that will receive the notifications |