Open Health Hub FHIR Implementation Guide
0.1.0 - v0.1.0

Open Health Hub FHIR 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: OHH Subscription

Official URL: https://api.openhealthhub.com/OpenHealthhub/fhir/4/StructureDefinition/ohh-subscription | Version: 0.1.0
Active as of 2025-12-03 | Computable Name: OhhSubscription

Subscriptions are used to trigger a webhook request when a resource that matches the criteria has been created or updated.

### Scope and Usage

Subscription can be used to get notified about changes to resources. Currently only subscription on these resources can be created:

- QuestionnaireResponse
- PlanDefinition
- CarePlan

Usages:

- Examples for this Profile: Subscription/0c41aec8-286c-4a7d-8714-8137a199f46e and Subscription/ExampleOhhSubscriptionWithPayload
- CapabilityStatements using this Profile: OHH FHIR API

You can also check for usages in the FHIR IG Statistics

### Formal Views of Profile Content

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

- Differential Table
- Key Elements Table
- Snapshot Table
- Statistics/References
- All

This structure is derived from Subscription

Name | Flags | Card. | Type | Description & Constraints Filter: Bindings Constraints Obligations
--- | --- | --- | --- | ---
Subscription |  | 0..* | Subscription | Server push subscription criteria
criteria | C | 1..1 | string | Rule for server push Constraints: ohh-subscription-criteria
channel |  |  |  |
type |  | 1..1 | code | rest-hook | websocket | email | sms | message Fixed Value: rest-hook
Documentation for this format

#### Constraints

Id | Grade | Path(s) | Description | Expression
ohh-subscription-criteria | error | Subscription.criteria | Criteria can only be on QuestionnaireResponse, PlanDefinition, or CarePlan | `matches('^(QuestionnaireResponse|PlanDefinition|CarePlan).*')`

Name | Flags | Card. | Type | Description & Constraints Filter: Bindings Constraints Obligations
--- | --- | --- | --- | ---
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.
reason | Σ | 1..1 | string | Description of why this subscription was created
criteria | Σ C | 1..1 | string | Rule for server push Constraints: ohh-subscription-criteria
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. Fixed Value: rest-hook
Documentation for this format

#### Terminology Bindings

Path | Status | Usage | ValueSet | Version | Source
Subscription.status | Base | required | SubscriptionStatus | 📍4.0.1 | FHIR Std.
Subscription.channel.​type | Base | required | SubscriptionChannelType | 📍4.0.1 | FHIR Std.

#### Constraints

Id | Grade | Path(s) | Description | Expression
dom-2 | error | Subscription | If the resource is contained in another resource, it SHALL NOT contain nested Resources | `contained.contained.empty()`
dom-3 | error | Subscription | If 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-4 | error | Subscription | If 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-5 | error | Subscription | If a resource is contained in another resource, it SHALL NOT have a security label | `contained.meta.security.empty()`
dom-6 | best practice | Subscription | A resource should have narrative for robust management | `text.`div`.exists()`
ele-1 | error | **ALL** elements | All FHIR elements must have a @value or children | `hasValue() or (children().count() > id.count())`
ext-1 | error | **ALL** extensions | Must have either extensions or value[x], not both | `extension.exists() != value.exists()`
ohh-subscription-criteria | error | Subscription.criteria | Criteria can only be on QuestionnaireResponse, PlanDefinition, or CarePlan | `matches('^(QuestionnaireResponse|PlanDefinition|CarePlan).*')`

Name | Flags | Card. | Type | Description & Constraints Filter: Bindings Constraints Obligations
--- | --- | --- | --- | ---
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
language |  | 0..1 | code | Language of the resource content Binding: CommonLanguages (preferred): A human language.
Additional Bindings | Purpose
AllLanguages | Max Binding
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 | Σ C | 1..1 | string | Rule for server push Constraints: ohh-subscription-criteria
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. Fixed Value: rest-hook
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
Documentation for this format

#### Terminology Bindings

Path | Status | Usage | ValueSet | Version | Source
Subscription.language | Base | preferred | Common Languages | 📍4.0.1 | FHIR Std.
Subscription.status | Base | required | SubscriptionStatus | 📍4.0.1 | FHIR Std.
Subscription.channel.​type | Base | required | SubscriptionChannelType | 📍4.0.1 | FHIR Std.
Subscription.channel.​payload | Base | required | MimeType | 📍4.0.1 | FHIR Std.

#### Constraints

Id | Grade | Path(s) | Description | Expression
dom-2 | error | Subscription | If the resource is contained in another resource, it SHALL NOT contain nested Resources | `contained.contained.empty()`
dom-3 | error | Subscription | If 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-4 | error | Subscription | If 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-5 | error | Subscription | If a resource is contained in another resource, it SHALL NOT have a security label | `contained.meta.security.empty()`
dom-6 | best practice | Subscription | A resource should have narrative for robust management | `text.`div`.exists()`
ele-1 | error | **ALL** elements | All FHIR elements must have a @value or children | `hasValue() or (children().count() > id.count())`
ext-1 | error | **ALL** extensions | Must have either extensions or value[x], not both | `extension.exists() != value.exists()`
ohh-subscription-criteria | error | Subscription.criteria | Criteria can only be on QuestionnaireResponse, PlanDefinition, or CarePlan | `matches('^(QuestionnaireResponse|PlanDefinition|CarePlan).*')`

This structure is derived from Subscription

Summary

Fixed: 1 element

Differential View

This structure is derived from Subscription

Name | Flags | Card. | Type | Description & Constraints Filter: Bindings Constraints Obligations
--- | --- | --- | --- | ---
Subscription |  | 0..* | Subscription | Server push subscription criteria
criteria | C | 1..1 | string | Rule for server push Constraints: ohh-subscription-criteria
channel |  |  |  |
type |  | 1..1 | code | rest-hook | websocket | email | sms | message Fixed Value: rest-hook
Documentation for this format

#### Constraints

Id | Grade | Path(s) | Description | Expression
ohh-subscription-criteria | error | Subscription.criteria | Criteria can only be on QuestionnaireResponse, PlanDefinition, or CarePlan | `matches('^(QuestionnaireResponse|PlanDefinition|CarePlan).*')`

Key Elements View

Name | Flags | Card. | Type | Description & Constraints Filter: Bindings Constraints Obligations
--- | --- | --- | --- | ---
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.
reason | Σ | 1..1 | string | Description of why this subscription was created
criteria | Σ C | 1..1 | string | Rule for server push Constraints: ohh-subscription-criteria
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. Fixed Value: rest-hook
Documentation for this format

#### Terminology Bindings

Path | Status | Usage | ValueSet | Version | Source
Subscription.status | Base | required | SubscriptionStatus | 📍4.0.1 | FHIR Std.
Subscription.channel.​type | Base | required | SubscriptionChannelType | 📍4.0.1 | FHIR Std.

#### Constraints

Id | Grade | Path(s) | Description | Expression
dom-2 | error | Subscription | If the resource is contained in another resource, it SHALL NOT contain nested Resources | `contained.contained.empty()`
dom-3 | error | Subscription | If 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-4 | error | Subscription | If 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-5 | error | Subscription | If a resource is contained in another resource, it SHALL NOT have a security label | `contained.meta.security.empty()`
dom-6 | best practice | Subscription | A resource should have narrative for robust management | `text.`div`.exists()`
ele-1 | error | **ALL** elements | All FHIR elements must have a @value or children | `hasValue() or (children().count() > id.count())`
ext-1 | error | **ALL** extensions | Must have either extensions or value[x], not both | `extension.exists() != value.exists()`
ohh-subscription-criteria | error | Subscription.criteria | Criteria can only be on QuestionnaireResponse, PlanDefinition, or CarePlan | `matches('^(QuestionnaireResponse|PlanDefinition|CarePlan).*')`

Snapshot View

Name | Flags | Card. | Type | Description & Constraints Filter: Bindings Constraints Obligations
--- | --- | --- | --- | ---
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
language |  | 0..1 | code | Language of the resource content Binding: CommonLanguages (preferred): A human language.
Additional Bindings | Purpose
AllLanguages | Max Binding
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 | Σ C | 1..1 | string | Rule for server push Constraints: ohh-subscription-criteria
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. Fixed Value: rest-hook
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
Documentation for this format

#### Terminology Bindings

Path | Status | Usage | ValueSet | Version | Source
Subscription.language | Base | preferred | Common Languages | 📍4.0.1 | FHIR Std.
Subscription.status | Base | required | SubscriptionStatus | 📍4.0.1 | FHIR Std.
Subscription.channel.​type | Base | required | SubscriptionChannelType | 📍4.0.1 | FHIR Std.
Subscription.channel.​payload | Base | required | MimeType | 📍4.0.1 | FHIR Std.

#### Constraints

Id | Grade | Path(s) | Description | Expression
dom-2 | error | Subscription | If the resource is contained in another resource, it SHALL NOT contain nested Resources | `contained.contained.empty()`
dom-3 | error | Subscription | If 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-4 | error | Subscription | If 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-5 | error | Subscription | If a resource is contained in another resource, it SHALL NOT have a security label | `contained.meta.security.empty()`
dom-6 | best practice | Subscription | A resource should have narrative for robust management | `text.`div`.exists()`
ele-1 | error | **ALL** elements | All FHIR elements must have a @value or children | `hasValue() or (children().count() > id.count())`
ext-1 | error | **ALL** extensions | Must have either extensions or value[x], not both | `extension.exists() != value.exists()`
ohh-subscription-criteria | error | Subscription.criteria | Criteria can only be on QuestionnaireResponse, PlanDefinition, or CarePlan | `matches('^(QuestionnaireResponse|PlanDefinition|CarePlan).*')`

This structure is derived from Subscription

Summary

Fixed: 1 element

Other representations of profile: CSV, Excel, Schematron

### Notes:

### Creating a Subscription

To create a Subscription to get notified about changes you’ll need to have an endpoint/URL available that can handle the notification requests.

If you want subscriptions to only be valid until a specific time, you can specify the end value of a subscription. This can be helpful if you specify an authorization token that has a limited lifetime in the headers. Note that you should keep track of expired subscriptions yourself. We won’t create new subscriptions if they expire. No notifications will be sent for this subscription after the specified timestamp. The status of the subscription will then also change to `off`.

When creating a Subscription, you can choose to also retrieve the content with the notification by setting the payload to one of the 2 allowed values [application/fhir+json, application/fhir+xml]. If you don’t want to receive the content, you’ll need to execute the request defined in the criteria to retrieve the items.

If you choose to receive notifications by setting payload, be sure to enter the correct URL to prevent data being sent to anotherserver.

#### With Payload

If you have set the payload to one of the allowed values, we’ll send the notifications with the (related) content of the subscribed resource in a Bundle of type history.

#### Headers

If your server endpoint needs specific headers in the HTTP Post request, you can add them in the `channel.header` field. This can, for example, be used when the endpoint is secured with authentication. You can, for example, add an `Authorization: Bearer <jwttoken>` value to the headers. When the notification is posted, these headers will be added to the request.

#### Supported criteria

We currently support subscriptions on PlanDefinition, QuestionnaireResponse and CarePlan:

##### PlanDefinition

You can register a Subscription on PlanDefinitions to receive notification when new programs for your client are published or if changes occur to a specific program by adding an _id query parameter to the criteria.

When the `payload` property has been set, the posted Bundle will contain the PlanDefinition that was changed/created.

##### QuestionnaireResponse

You can register a Subscription on QuestionnaireResponse to receive notification when new answers for a questionnaire have become available. Currently, you can register for notifications on all responses or on responses for a specific program/PlanDefinition. To listen for responses for a specific program, you’ll need to add the `based-on.instantiates-canonical` query parameter to your criteria and set the value to the UUID of the program you want to receive notifications for.

When the `payload` property has been set, the posted Bundle will contain the QuestionnaireResponse (with encrypted values) and the Questionnaire that corresponds to this QuestionnaireResponse. If you created the Subscription via the FHIR Viewer Gateway, the gateway will handle decryption of the QuestionnaireReponse

##### CarePlan

You can register a Subscription on CarePlan to receive notification when a CarePlan is created or updated, or when a questionnaire that is part of the CarePlan has been filled out. Currently, you can register for notifications on all CarePlans, CarePlans for a specific program/PlanDefinition, or for a specific CarePlan. To listen for CarePlans for a specific program, you’ll need to add the `instantiates-canonical` query parameter to your criteria and set the value to the UUID of the program you want to receive notifications for. When you want to receive notifications for a specific CarePlan, you can use the `_id` query parameter with the ID of the CarePlan as value.

When the `payload` property has been set, the posted Bundle will contain the CarePlan that was updated/created.