Ontario Health eForms Implementation Guide
0.1.0 - ci-build CA-ON

Ontario Health eForms Implementation Guide - Local Development build (v0.1.0) built by the FHIR (HL7® FHIR® Standard) Build Tools. See the Directory of published versions

Resource Profile: Subscription Profile

Official URL: http://ontario.ca/fhir/eforms/StructureDefinition/EFormSubscription Version: 0.1.0
Active as of 2025-07-16 Computable Name: EFormsSubscription

Subscription Profile for OH eForms, based on the R4 version.

A Subscription is a publish-subscribe (pub/sub) mechanism built into the FHIR specification. Subscriptions are defined using the Subscription resource, which specifies what type of data is being subscribed to and how the recipient should be notified.

status - When a Subscription is created by a client, it should have a status of requested. Smile CDR will process this Subscription, and if it is valid, the status will automatically be changed to active, meaning that the Subscription is now being processed. criteria - This is a FHIR search query URL that will be used to determine which resources apply to the Subscription. These resources will trigger a notification when they change. See Criteria below for more information. channel.type - This is the mechanism for delivery, such as rest-hook, websocket, email, sms, or message. See Channel Types for more information. channel.endpoint - For channel types that require the server to initiate a connection to the client, this is the URL of the endpoint to which the server should connect. channel.payload - This is the MIME type encoding to use (e.g. application/fhir+json for JSON data). channel.extension` - Providing an extension allows finer control of subscription handling. Some extensions are channel specific, while others are used to define retry handling.

With Subscriptions enabled, Smile creates a Matching Queue and sends all created/updated QuestionnaireResponse or Communication resources to that queue. This queue is drained by a Subscription Matching module. The Subscription Matcher module uses its FHIR Storage module to retrieve two resource types required for subscription matching: Subscription and SearchParameter. The Subscription Matcher module maintains in-memory caches of both of these resources that it updates from its FHIR Storage module every 60 seconds.

In the requirements, eForms is required to send email notifications whenever a QuestionnaireResponse or Communication Resource is submitted by the form filler to the FHIR Repository. While Smile does offer the ability to trigger email notifications via smtp, OH has a requirement that their AWS Simple Email Service (SES) must be used in order to send notifications. In addition to notifications, Subscriptions will also be utilized to trigger the integration with the OH ObjectStore

AWS SES Delivery - When an QuestionnaireResponse or Communication resource is submitted and the subscription is triggered in the FHIR Server, Smile will trigger a RESTful API call to the AWS SES API.

Object Store Delivery - This Subscription class will automatically invoke an SDC extraction by invoking the QuestionnaireResponse/$extraction operation which will convert the matched QuestionnaireResponse resource into a MessageBundle as defined by the ObjectStore Implementation Guide (IG).

A custom Subscription Delivery class is invoked whenever the matching criteria defined in the Subscription Resource for Object Store integration.

Search Parameters

Standard FHIR Search Parameters

This profile supports all standard Subscription search parameters:

Name Type Description
contact token Contact details for the subscription
criteria string The search rules used to determine when to send a notification
payload token The mime-type of the notification payload
status token The current state of the subscription
type token The type of channel for the sent notifications
url uri The uri that will receive the notifications

Usage Examples

GET [base]/Subscription?status=active
GET [base]/Subscription?type=rest-hook
GET [base]/Subscription?criteria=Task?status=completed
GET [base]/Subscription?contact=System/notification-service

Implementation Notes

eForms Subscription Context

  • Enables real-time notifications for form workflow events
  • May subscribe to Task status changes (e.g., when forms are completed)
  • Can notify external systems when ServiceRequests are created

Security Considerations

  • Should use appropriate criteria to filter relevant events
  • Consider security implications for webhook endpoints
  • Implement proper authentication for notification delivery

Usages:

  • This Profile is not used by any profiles in this Implementation Guide

Formal Views of Profile Content

Description of Profiles, Differentials, Snapshots and how the different presentations work.

NameFlagsCard.TypeDescription & Constraints    Filter: Filtersdoco
.. Subscription 0..* Subscription Server push subscription criteria
... implicitRules ?!Σ 0..1 uri A set of rules under which this content was created
... modifierExtension ?! 0..* Extension Extensions that cannot be ignored
... status ?!Σ 1..1 code requested | active | error | off
Binding: SubscriptionStatus (required): The status of a subscription.
... criteria Σ 1..1 string Rule for server push
... channel Σ 1..1 BackboneElement The channel on which to report matches to the criteria
.... modifierExtension ?!Σ 0..* Extension Extensions that cannot be ignored even if unrecognized
.... type Σ 1..1 code rest-hook | websocket | email | sms | message
Binding: SubscriptionChannelType (required): The type of method used to execute a subscription.

doco Documentation for this format

Terminology Bindings

PathConformanceValueSetURI
Subscription.statusrequiredSubscriptionStatus
http://hl7.org/fhir/ValueSet/subscription-status|4.0.1
From the FHIR Standard
Subscription.channel.typerequiredSubscriptionChannelType
http://hl7.org/fhir/ValueSet/subscription-channel-type|4.0.1
From the FHIR Standard

Constraints

IdGradePath(s)DetailsRequirements
dom-2errorSubscriptionIf the resource is contained in another resource, it SHALL NOT contain nested Resources
: contained.contained.empty()
dom-3errorSubscriptionIf the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource
: contained.where((('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(canonical) = '#').exists()).not()).trace('unmatched', id).empty()
dom-4errorSubscriptionIf a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated
: contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()
dom-5errorSubscriptionIf a resource is contained in another resource, it SHALL NOT have a security label
: contained.meta.security.empty()
dom-6best practiceSubscriptionA resource should have narrative for robust management
: text.`div`.exists()
ele-1error**ALL** elementsAll FHIR elements must have a @value or children
: hasValue() or (children().count() > id.count())
ext-1error**ALL** extensionsMust have either extensions or value[x], not both
: extension.exists() != value.exists()

This structure is derived from Subscription

NameFlagsCard.TypeDescription & Constraints    Filter: Filtersdoco
.. Subscription 0..* Subscription Server push subscription criteria

doco Documentation for this format
NameFlagsCard.TypeDescription & Constraints    Filter: Filtersdoco
.. Subscription 0..* Subscription Server push subscription criteria
... id Σ 0..1 id Logical id of this artifact
... meta Σ 0..1 Meta Metadata about the resource
... implicitRules ?!Σ 0..1 uri A set of rules under which this content was created
... text 0..1 Narrative Text summary of the resource, for human interpretation
This profile does not constrain the narrative in regard to content, language, or traceability to data elements
... contained 0..* Resource Contained, inline Resources
... extension 0..* Extension Additional content defined by implementations
... modifierExtension ?! 0..* Extension Extensions that cannot be ignored
... status ?!Σ 1..1 code requested | active | error | off
Binding: SubscriptionStatus (required): The status of a subscription.
... contact Σ 0..* ContactPoint Contact details for source (e.g. troubleshooting)
... end Σ 0..1 instant When to automatically delete the subscription
... reason Σ 1..1 string Description of why this subscription was created
... criteria Σ 1..1 string Rule for server push
... error Σ 0..1 string Latest error note
... channel Σ 1..1 BackboneElement The channel on which to report matches to the criteria
.... id 0..1 string Unique id for inter-element referencing
.... extension 0..* Extension Additional content defined by implementations
.... modifierExtension ?!Σ 0..* Extension Extensions that cannot be ignored even if unrecognized
.... type Σ 1..1 code rest-hook | websocket | email | sms | message
Binding: SubscriptionChannelType (required): The type of method used to execute a subscription.
.... endpoint Σ 0..1 url Where the channel points to
.... payload Σ 0..1 code MIME type to send, or omit for no payload
Binding: Mime Types (required): The mime type of an attachment. Any valid mime type is allowed.
.... header Σ 0..* string Usage depends on the channel type

doco Documentation for this format

Terminology Bindings

PathConformanceValueSetURI
Subscription.languagepreferredCommonLanguages
http://hl7.org/fhir/ValueSet/languages
From the FHIR Standard
Additional Bindings Purpose
AllLanguages Max Binding
Subscription.statusrequiredSubscriptionStatus
http://hl7.org/fhir/ValueSet/subscription-status|4.0.1
From the FHIR Standard
Subscription.channel.typerequiredSubscriptionChannelType
http://hl7.org/fhir/ValueSet/subscription-channel-type|4.0.1
From the FHIR Standard
Subscription.channel.payloadrequiredMime Types(a valid code from urn:ietf:bcp:13)
http://hl7.org/fhir/ValueSet/mimetypes|4.0.1
From the FHIR Standard

Constraints

IdGradePath(s)DetailsRequirements
dom-2errorSubscriptionIf the resource is contained in another resource, it SHALL NOT contain nested Resources
: contained.contained.empty()
dom-3errorSubscriptionIf the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource
: contained.where((('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(canonical) = '#').exists()).not()).trace('unmatched', id).empty()
dom-4errorSubscriptionIf a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated
: contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()
dom-5errorSubscriptionIf a resource is contained in another resource, it SHALL NOT have a security label
: contained.meta.security.empty()
dom-6best practiceSubscriptionA resource should have narrative for robust management
: text.`div`.exists()
ele-1error**ALL** elementsAll FHIR elements must have a @value or children
: hasValue() or (children().count() > id.count())
ext-1error**ALL** extensionsMust have either extensions or value[x], not both
: extension.exists() != value.exists()

This structure is derived from Subscription

Summary

Key Elements View

NameFlagsCard.TypeDescription & Constraints    Filter: Filtersdoco
.. Subscription 0..* Subscription Server push subscription criteria
... implicitRules ?!Σ 0..1 uri A set of rules under which this content was created
... modifierExtension ?! 0..* Extension Extensions that cannot be ignored
... status ?!Σ 1..1 code requested | active | error | off
Binding: SubscriptionStatus (required): The status of a subscription.
... criteria Σ 1..1 string Rule for server push
... channel Σ 1..1 BackboneElement The channel on which to report matches to the criteria
.... modifierExtension ?!Σ 0..* Extension Extensions that cannot be ignored even if unrecognized
.... type Σ 1..1 code rest-hook | websocket | email | sms | message
Binding: SubscriptionChannelType (required): The type of method used to execute a subscription.

doco Documentation for this format

Terminology Bindings

PathConformanceValueSetURI
Subscription.statusrequiredSubscriptionStatus
http://hl7.org/fhir/ValueSet/subscription-status|4.0.1
From the FHIR Standard
Subscription.channel.typerequiredSubscriptionChannelType
http://hl7.org/fhir/ValueSet/subscription-channel-type|4.0.1
From the FHIR Standard

Constraints

IdGradePath(s)DetailsRequirements
dom-2errorSubscriptionIf the resource is contained in another resource, it SHALL NOT contain nested Resources
: contained.contained.empty()
dom-3errorSubscriptionIf the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource
: contained.where((('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(canonical) = '#').exists()).not()).trace('unmatched', id).empty()
dom-4errorSubscriptionIf a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated
: contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()
dom-5errorSubscriptionIf a resource is contained in another resource, it SHALL NOT have a security label
: contained.meta.security.empty()
dom-6best practiceSubscriptionA resource should have narrative for robust management
: text.`div`.exists()
ele-1error**ALL** elementsAll FHIR elements must have a @value or children
: hasValue() or (children().count() > id.count())
ext-1error**ALL** extensionsMust have either extensions or value[x], not both
: extension.exists() != value.exists()

Differential View

This structure is derived from Subscription

NameFlagsCard.TypeDescription & Constraints    Filter: Filtersdoco
.. Subscription 0..* Subscription Server push subscription criteria

doco Documentation for this format

Snapshot View

NameFlagsCard.TypeDescription & Constraints    Filter: Filtersdoco
.. Subscription 0..* Subscription Server push subscription criteria
... id Σ 0..1 id Logical id of this artifact
... meta Σ 0..1 Meta Metadata about the resource
... implicitRules ?!Σ 0..1 uri A set of rules under which this content was created
... text 0..1 Narrative Text summary of the resource, for human interpretation
This profile does not constrain the narrative in regard to content, language, or traceability to data elements
... contained 0..* Resource Contained, inline Resources
... extension 0..* Extension Additional content defined by implementations
... modifierExtension ?! 0..* Extension Extensions that cannot be ignored
... status ?!Σ 1..1 code requested | active | error | off
Binding: SubscriptionStatus (required): The status of a subscription.
... contact Σ 0..* ContactPoint Contact details for source (e.g. troubleshooting)
... end Σ 0..1 instant When to automatically delete the subscription
... reason Σ 1..1 string Description of why this subscription was created
... criteria Σ 1..1 string Rule for server push
... error Σ 0..1 string Latest error note
... channel Σ 1..1 BackboneElement The channel on which to report matches to the criteria
.... id 0..1 string Unique id for inter-element referencing
.... extension 0..* Extension Additional content defined by implementations
.... modifierExtension ?!Σ 0..* Extension Extensions that cannot be ignored even if unrecognized
.... type Σ 1..1 code rest-hook | websocket | email | sms | message
Binding: SubscriptionChannelType (required): The type of method used to execute a subscription.
.... endpoint Σ 0..1 url Where the channel points to
.... payload Σ 0..1 code MIME type to send, or omit for no payload
Binding: Mime Types (required): The mime type of an attachment. Any valid mime type is allowed.
.... header Σ 0..* string Usage depends on the channel type

doco Documentation for this format

Terminology Bindings

PathConformanceValueSetURI
Subscription.languagepreferredCommonLanguages
http://hl7.org/fhir/ValueSet/languages
From the FHIR Standard
Additional Bindings Purpose
AllLanguages Max Binding
Subscription.statusrequiredSubscriptionStatus
http://hl7.org/fhir/ValueSet/subscription-status|4.0.1
From the FHIR Standard
Subscription.channel.typerequiredSubscriptionChannelType
http://hl7.org/fhir/ValueSet/subscription-channel-type|4.0.1
From the FHIR Standard
Subscription.channel.payloadrequiredMime Types(a valid code from urn:ietf:bcp:13)
http://hl7.org/fhir/ValueSet/mimetypes|4.0.1
From the FHIR Standard

Constraints

IdGradePath(s)DetailsRequirements
dom-2errorSubscriptionIf the resource is contained in another resource, it SHALL NOT contain nested Resources
: contained.contained.empty()
dom-3errorSubscriptionIf the resource is contained in another resource, it SHALL be referred to from elsewhere in the resource or SHALL refer to the containing resource
: contained.where((('#'+id in (%resource.descendants().reference | %resource.descendants().as(canonical) | %resource.descendants().as(uri) | %resource.descendants().as(url))) or descendants().where(reference = '#').exists() or descendants().where(as(canonical) = '#').exists() or descendants().where(as(canonical) = '#').exists()).not()).trace('unmatched', id).empty()
dom-4errorSubscriptionIf a resource is contained in another resource, it SHALL NOT have a meta.versionId or a meta.lastUpdated
: contained.meta.versionId.empty() and contained.meta.lastUpdated.empty()
dom-5errorSubscriptionIf a resource is contained in another resource, it SHALL NOT have a security label
: contained.meta.security.empty()
dom-6best practiceSubscriptionA resource should have narrative for robust management
: text.`div`.exists()
ele-1error**ALL** elementsAll FHIR elements must have a @value or children
: hasValue() or (children().count() > id.count())
ext-1error**ALL** extensionsMust have either extensions or value[x], not both
: extension.exists() != value.exists()

This structure is derived from Subscription

Summary

 

Other representations of profile: CSV, Excel, Schematron