This
page
is
part
of
the
FHIR
Specification
(v4.0.1:
R4
-
Mixed
Normative
and
STU
)
in
it's
permanent
home
(it
will
always
be
available
at
this
URL).
(v4.2.0:
R5
Preview
#1).
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
:
|
Trial Use | Security Category : Business | Compartments : Not linked to any defined compartments |
The
subscription
resource
is
used
to
define
a
push-based
subscription
from
describes
a
server
particular
client's
request
to
another
system.
Once
a
subscription
is
registered
with
the
server,
the
server
checks
every
resource
that
is
created
or
updated,
and
if
the
resource
matches
the
given
criteria,
it
sends
be
notified
about
a
message
on
the
defined
"channel"
so
that
another
system
can
take
an
appropriate
action.
Topic.
The
subscription
resource
is
used
to
establish
proactive
event
notifications
from
a
FHIR
server
to
another
system.
Subscribers
request
event
notifications
within
a
predefined
Topic
that
the
server
supports,
and
can
further
refine
their
notifications
by
supplying
filters.
Each
Topic
resource
defines
a
set
of
allowed
filters
(
Topic.canFilterBy
),
which
a
subscriber
refer
to
within
a
Subscription
resource
(
Subscription.filterBy
).
Once
a
subscription
is
created,
any
newly
created
or
updated
resources
event
matching
a
specified
Topic
that
meet
meets
the
filtering
criteria
in
the
resource
will
cause
a
notification
to
be
sent
using
the
provided
channel.
The
criteria
Subscriptions
are
Search
strings
that
have
the
same
interpretation
as
active
resources;
a
server
can
only
accept
a
subscription
if
they
were
appended
to
the
base
URL
and
submitted
using
the
REST
API.
Note
that
the
search
criteria
are
applied
to
the
new
value
of
it
will
execute
the
resource.
specified
channel
for
any
resources
subsequently
received.
The
consequence
of
this
is
that
there
is
no
notification
when
a
resource
is
deleted,
or
when
a
resource
subscription
is
updated
so
that
it
no
longer
meets
active
once
it
is
deleted
from
the
criteria.
server.
The
server
is
able
to
send
By
adjusting
Subscription.channel.payload.content
,
subscribers
can
request
event
notifications
without
any
information
about
the
matching
resource,
that
include
full
resource
content;
or
with
just
the
entire
resource.
ID
of
the
triggering
resource;
or
an
empty
notification
body.
Several
different
types
of
channels
are
supported:
defined
in
the
core
specification:
Subscription.channel.endpoint
URL
https://...
)
Subscription.channel.endpoint
email
mailto:...
)
Subscription.channel.endpoint
URI
Additional
channel
types
can
be
defined
by
external
implementation
guides.
See
below
for
further
discussion
of
the
various
channels.
Note
that
sending
the
entire
resource
creates
security
concerns
that
must
be
managed
by
the
server.
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.
As
an
alternative
to
subscriptions,
the
RESTful
API
describes
a
polling-based
subscription
method
for
observing
events
using
bundles
and
the
history
operation
.
This
method
of
polling
allows
for
a
much
tighter
relationship
between
the
client
and
the
server
that
doesn't
involve
missing
updates
and/or
deletes.
When
using
the
Subscription
resource,
the
FHIR
server
combines
the
roles
of
publisher
and
information
distributer.
Other
arrangements
of
the
publish
and
subscribe
pattern
describe
separate
agents
for
the
two
roles.
Implementers
may
implement
the
Subscription
resource
using
an
architecture
with
separate
agents,
or
using
any
other
pub/sub
architectire
(e.g.
see
FHIRCast
,
or,
more
generally,
W3C
Pub/Sub
).
TODO: Does this imply that Subscriptions can be built on top of FHIRCast?
No resources refer to this resource directly.
This resource does not implement any patterns.
Structure
| Name | Flags | Card. | Type |
Description
&
Constraints
|
|---|---|---|---|---|
|
|
DomainResource |
Elements defined in Ancestors: id , meta , implicitRules , language , text , contained , extension , modifierExtension |
|
| Σ | 0..* | Identifier |
Additional
identifiers
(business
identifier)
|
![]() ![]() | Σ | 0..1 | string | Human readable name for this subscription |
|
?! Σ | 1..1 | code |
requested
|
active
|
error
|
off
SubscriptionStatus ( Required ) |
| Σ | 1..1 | Reference ( Topic ) | Reference to the topic being subscribed to |
![]() ![]() |
Σ | 0..* | ContactPoint |
Contact
details
for
source
(e.g.
troubleshooting)
|
|
Σ | 0..1 | instant | When to automatically delete the subscription |
|
Σ | 0..1 | string | Description of why this subscription was created |
| Σ | 0..* | BackboneElement |
Criteria
for
narrowing
the
topic
stream
|
|
Σ | 1..1 | string |
|
|
Σ | 0..1 | code |
=
|
in
|
not-in
|
above
|
below
SubscriptionFilterByMatchType ( Required ) |
![]() ![]() ![]() | Σ | 1..1 | string | Literal value or resource path |
![]() ![]() | Σ | 0..* | CodeableConcept |
Latest
error
code
or
note
Subscription Error Codes ( Example ) |
| Σ | 0..1 | unsignedInt | Notification event counter |
![]() ![]() |
Σ | 1..1 | BackboneElement | The channel on which to report matches to the criteria |
|
Σ | 1..1 |
|
rest-hook
|
websocket
|
email
|
|
|
Σ | 0..1 | url | Where the channel points to |
| Σ | 0..* | string |
Usage
depends
on
the
channel
type
|
| Σ | 0..1 | unsignedInt | Interval in seconds to send 'heartbeat' notification |
![]() ![]() ![]() |
Σ | 0..1 | BackboneElement | Payload definition |
![]() ![]() ![]() ![]() |
Σ | 0..1 | code |
MIME
type
to
send,
or
omit
for
no
payload
MimeType ( Required ) |
|
Σ |
|
|
SubscriptionPayloadContent ( Required ) |
Documentation
for
this
format
|
||||
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 --> <topic><!-- 1..1 Reference(Topic) Reference to the 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 -->
< < <<reason value="[string]"/><!-- 0..1 Description of why this subscription was created --> <filterBy> <!-- 0..* Criteria for narrowing the topic stream --> <name value="[string]"/><!-- 1..1 Filter label defined in Topic --> <matchType value="[code]"/><!-- 0..1 = | in | not-in | above | below --> <value value="[string]"/><!-- 1..1 Literal value or resource path --> </filterBy> <error><!-- 0..* CodeableConcept Latest error code or note --></error> <eventCount value="[unsignedInt]"/><!-- 0..1 Notification event counter --> <channel> <!-- 1..1 The channel on which to report matches to the criteria --><<type><!-- 1..1 CodeableConcept rest-hook | websocket | email | message --></type> <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 --> <payload> <!-- 0..1 Payload definition --> <contentType value="[code]"/><!-- 0..1 MIME type to send, or omit for no payload --> <content value="[code]"/><!-- 0..1 empty | id-only | full-resource --> </payload> </channel> </Subscription>
JSON Template
{
"resourceType" : "",
"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
"topic" : { Reference(Topic) }, // R! Reference to the topic being subscribed to
"contact" : [{ ContactPoint }], // Contact details for source (e.g. troubleshooting)
"end" : "<instant>", // When to automatically delete the subscription
"
"
"
"reason" : "<string>", // Description of why this subscription was created
"filterBy" : [{ // Criteria for narrowing the topic stream
"name" : "<string>", // R! Filter label defined in Topic
"matchType" : "<code>", // = | in | not-in | above | below
"value" : "<string>" // R! Literal value or resource path
}],
"error" : [{ CodeableConcept }], // Latest error code or note
"eventCount" : "<unsignedInt>", // Notification event counter
"channel" : { // R! The channel on which to report matches to the criteria
"
"type" : { CodeableConcept }, // R! rest-hook | websocket | email | message
"endpoint" : "<url>", // Where the channel points to
"
"
"header" : ["<string>"], // Usage depends on the channel type
"heartbeatPeriod" : "<unsignedInt>", // Interval in seconds to send 'heartbeat' notification
"payload" : { // Payload definition
"contentType" : "<code>", // MIME type to send, or omit for no payload
"content" : "<code>" // empty | id-only | full-resource
}
}
}
Turtle Template
@prefix fhir: <http://hl7.org/fhir/> .![]()
[ a 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 fhir:Subscription.topic [ Reference(Topic) ]; # 1..1 Reference to the 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 subscriptionfhir: fhir: fhir:fhir:Subscription.reason [ string ]; # 0..1 Description of why this subscription was created fhir:Subscription.filterBy [ # 0..* Criteria for narrowing the topic stream fhir:Subscription.filterBy.name [ string ]; # 1..1 Filter label defined in Topic fhir:Subscription.filterBy.matchType [ code ]; # 0..1 = | in | not-in | above | below fhir:Subscription.filterBy.value [ string ]; # 1..1 Literal value or resource path ], ...; fhir:Subscription.error [ CodeableConcept ], ... ; # 0..* Latest error code or note fhir:Subscription.eventCount [ unsignedInt ]; # 0..1 Notification event counter fhir:Subscription.channel [ # 1..1 The channel on which to report matches to the criteriafhir:fhir:Subscription.channel.type [ CodeableConcept ]; # 1..1 rest-hook | websocket | email | message fhir:Subscription.channel.endpoint [ url ]; # 0..1 Where the channel points tofhir:fhir:Subscription.channel.header [ string ], ... ; # 0..* Usage depends on the channel type fhir:Subscription.channel.heartbeatPeriod [ unsignedInt ]; # 0..1 Interval in seconds to send 'heartbeat' notification fhir:Subscription.channel.payload [ # 0..1 Payload definition fhir:Subscription.channel.payload.contentType [ code ]; # 0..1 MIME type to send, or omit for no payload fhir:Subscription.channel.payload.content [ code ]; # 0..1 empty | id-only | full-resource ]; ]; ]
Changes since R3
| Subscription | |
| Subscription.identifier |
|
| Subscription.name |
|
| Subscription.status |
|
| Subscription.topic |
|
|
|
|
| Subscription.filterBy |
|
| Subscription.filterBy.name |
|
| Subscription.filterBy.matchType |
|
| Subscription.filterBy.value |
|
|
|
|
| Subscription.eventCount |
|
|
|
|
| Subscription.channel.heartbeatPeriod |
|
| Subscription.channel.payload |
|
| Subscription.channel.payload.contentType |
|
| Subscription.channel.payload.content |
|
|
|
|
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
|
|---|---|---|---|---|
|
|
DomainResource |
Elements defined in Ancestors: id , meta , implicitRules , language , text , contained , extension , modifierExtension |
|
| Σ | 0..* | Identifier |
Additional
identifiers
(business
identifier)
|
![]() ![]() | Σ | 0..1 | string | Human readable name for this subscription |
|
?! Σ | 1..1 | code |
requested
|
active
|
error
|
off
SubscriptionStatus ( Required ) |
| Σ | 1..1 | Reference ( Topic ) | Reference to the topic being subscribed to |
![]() ![]() |
Σ | 0..* | ContactPoint |
Contact
details
for
source
(e.g.
troubleshooting)
|
|
Σ | 0..1 | instant | When to automatically delete the subscription |
|
Σ | 0..1 | string | Description of why this subscription was created |
| Σ | 0..* | BackboneElement |
Criteria
for
narrowing
the
topic
stream
|
![]()
|
Σ | 1..1 | string |
|
|
Σ | 0..1 | code |
=
|
in
|
not-in
|
above
|
below
SubscriptionFilterByMatchType ( Required ) |
![]() ![]() ![]() | Σ | 1..1 | string | Literal value or resource path |
![]() ![]() | Σ | 0..* | CodeableConcept |
Latest
error
code
or
note
Subscription Error Codes ( Example ) |
| Σ | 0..1 | unsignedInt | Notification event counter |
![]() ![]() |
Σ | 1..1 | BackboneElement | The channel on which to report matches to the criteria |
|
Σ | 1..1 |
|
rest-hook
|
websocket
|
email
|
|
|
Σ | 0..1 | url | Where the channel points to |
| Σ | 0..* | string |
Usage
depends
on
the
channel
type
|
| Σ | 0..1 | unsignedInt | Interval in seconds to send 'heartbeat' notification |
![]() ![]() ![]() |
Σ | 0..1 | BackboneElement | Payload definition |
![]() ![]() ![]() ![]() |
Σ | 0..1 | code |
MIME
type
to
send,
or
omit
for
no
payload
MimeType ( Required ) |
|
Σ |
|
|
SubscriptionPayloadContent ( Required ) |
Documentation
for
this
format
|
||||
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 --> <topic><!-- 1..1 Reference(Topic) Reference to the 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 -->
< < <<reason value="[string]"/><!-- 0..1 Description of why this subscription was created --> <filterBy> <!-- 0..* Criteria for narrowing the topic stream --> <name value="[string]"/><!-- 1..1 Filter label defined in Topic --> <matchType value="[code]"/><!-- 0..1 = | in | not-in | above | below --> <value value="[string]"/><!-- 1..1 Literal value or resource path --> </filterBy> <error><!-- 0..* CodeableConcept Latest error code or note --></error> <eventCount value="[unsignedInt]"/><!-- 0..1 Notification event counter --> <channel> <!-- 1..1 The channel on which to report matches to the criteria --><<type><!-- 1..1 CodeableConcept rest-hook | websocket | email | message --></type> <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 --> <payload> <!-- 0..1 Payload definition --> <contentType value="[code]"/><!-- 0..1 MIME type to send, or omit for no payload --> <content value="[code]"/><!-- 0..1 empty | id-only | full-resource --> </payload> </channel> </Subscription>
JSON Template
{
"resourceType" : "",
"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
"topic" : { Reference(Topic) }, // R! Reference to the topic being subscribed to
"contact" : [{ ContactPoint }], // Contact details for source (e.g. troubleshooting)
"end" : "<instant>", // When to automatically delete the subscription
"
"
"
"reason" : "<string>", // Description of why this subscription was created
"filterBy" : [{ // Criteria for narrowing the topic stream
"name" : "<string>", // R! Filter label defined in Topic
"matchType" : "<code>", // = | in | not-in | above | below
"value" : "<string>" // R! Literal value or resource path
}],
"error" : [{ CodeableConcept }], // Latest error code or note
"eventCount" : "<unsignedInt>", // Notification event counter
"channel" : { // R! The channel on which to report matches to the criteria
"
"type" : { CodeableConcept }, // R! rest-hook | websocket | email | message
"endpoint" : "<url>", // Where the channel points to
"
"
"header" : ["<string>"], // Usage depends on the channel type
"heartbeatPeriod" : "<unsignedInt>", // Interval in seconds to send 'heartbeat' notification
"payload" : { // Payload definition
"contentType" : "<code>", // MIME type to send, or omit for no payload
"content" : "<code>" // empty | id-only | full-resource
}
}
}
Turtle Template
@prefix fhir: <http://hl7.org/fhir/> .![]()
[ a 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 fhir:Subscription.topic [ Reference(Topic) ]; # 1..1 Reference to the 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 subscriptionfhir: fhir: fhir:fhir:Subscription.reason [ string ]; # 0..1 Description of why this subscription was created fhir:Subscription.filterBy [ # 0..* Criteria for narrowing the topic stream fhir:Subscription.filterBy.name [ string ]; # 1..1 Filter label defined in Topic fhir:Subscription.filterBy.matchType [ code ]; # 0..1 = | in | not-in | above | below fhir:Subscription.filterBy.value [ string ]; # 1..1 Literal value or resource path ], ...; fhir:Subscription.error [ CodeableConcept ], ... ; # 0..* Latest error code or note fhir:Subscription.eventCount [ unsignedInt ]; # 0..1 Notification event counter fhir:Subscription.channel [ # 1..1 The channel on which to report matches to the criteriafhir:fhir:Subscription.channel.type [ CodeableConcept ]; # 1..1 rest-hook | websocket | email | message fhir:Subscription.channel.endpoint [ url ]; # 0..1 Where the channel points tofhir:fhir:Subscription.channel.header [ string ], ... ; # 0..* Usage depends on the channel type fhir:Subscription.channel.heartbeatPeriod [ unsignedInt ]; # 0..1 Interval in seconds to send 'heartbeat' notification fhir:Subscription.channel.payload [ # 0..1 Payload definition fhir:Subscription.channel.payload.contentType [ code ]; # 0..1 MIME type to send, or omit for no payload fhir:Subscription.channel.payload.content [ code ]; # 0..1 empty | id-only | full-resource ]; ]; ]
Changes since Release 3
| Subscription | |
| Subscription.identifier |
|
| Subscription.name |
|
| Subscription.status |
|
| Subscription.topic |
|
|
|
|
| Subscription.filterBy |
|
| Subscription.filterBy.name |
|
| Subscription.filterBy.matchType |
|
| Subscription.filterBy.value |
|
|
|
|
| Subscription.eventCount |
|
|
|
|
| Subscription.channel.heartbeatPeriod |
|
| Subscription.channel.payload |
|
| Subscription.channel.payload.contentType |
|
| Subscription.channel.payload.content |
|
|
|
|
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.)
See the Profiles & Extensions and the alternate definitions: Master Definition XML + JSON , XML Schema / Schematron + JSON Schema , ShEx (for Turtle ) + see the extensions , the spreadsheet version & the dependency analysis a
| Path | Definition | Type | Reference |
|---|---|---|---|
| Subscription.status | The status of a subscription. | Required | SubscriptionStatus |
| Subscription.filterBy.matchType | Operator to apply to filter label. | Required | SubscriptionFilterByMatchType |
| Subscription.error | Codes to represent subscription error details. | Example | SubscriptionErrorCodes |
| Subscription.channel.type | The type of method used to execute a subscription. |
|
|
|
|
The mime type of an attachment. Any valid mime type is allowed. | Required | Mime Types |
| Subscription.channel.payload.content | Codes to represent how much resource content to send in the notification payload. | Required | SubscriptionPayloadContent |
Trial-Use Note:
TODO
- Clarify relationship to FHIRcast or websub
Updates to "Managing Subscriptions and Errors"
- Discuss error codes (Extensible Codeable Concept)
- Define basic error codes here
- Need to discuss eventCount and error detection (insert appropriate examples/workflows)
Updates to "Tracking Subscription Notifications" SHOULD define what the AuditEvent looks like
Executing
Servers
are
responsible
for
following
FHIR
sercurity
guidance
.
Recommendations
specific
to
subscriptions
are
provided
below.
A subscription is a request for future event notifications. As with any client-initiated interaction, Subscriptions could request information that a client is not allowed to see, and servers SHALL enforce authorization in accordance with their policy requirements. Servers SHOULD take a Subscription's Topic and filters into account when authorizing the creation of a Subscription, and SHOULD ensure that authorization is (still) in place at the time of each event notification.
When
sending
an
event
notification,
servers
can
adopt
various
strategies
to
ensure
that
authorization
is
still
in
place.
Some
strategies
may
provide
imperfect
assurance
(e.g.,
a
server
might
rely
on
signed
tokens
with
some
pre-specified
lifetime
as
evidence
of
authorization).
In
addition
to
these
strategies,
servers
can
mitigate
the
risk
of
disclosing
sensitive
information
by
limiting
the
channels
documented
below
payload
types
it
supports
(e.g.,
by
prohibiting
certain
clients
from
requesting
full-resource
notification
payloads
and
relying
instead
on
id-only
payloads).
Subscription
resources
are
not
intended
to
be
secure
storage
for
secrets
(e.g.,
OAuth
Client
ID
or
Tokens,
etc.).
Implementers
MAY
use
their
judgement
on
including
limited-use
secrets
(e.g.,
a
token
supplied
in
Subscription.channel.header
to
verify
that
a
message
is
from
the
desired
source).
Each
channel
type
involves
the
server
sending
a
communication
that
will
could
reveal
information
about
the
client
and
server
relationship,
and,
if
the
entire
resource
is
sent,
as
well
as
sensitive
administrative
or
clinical
information
that
may
be
quite
sensitive
and/or
protected
under
law.
information.
Servers
are
responsible
for
ensuring
appropriate
security
is
employed
for
each
channel.
The
subscription
Subscription
resource
does
not
address
these
concerns
directly
-
directly;
it
is
assumed
that
these
are
administered
by
other
configuration
processes.
For
instance,
a
server
might
maintain
a
whitelist
of
acceptable
servers
endpoints
or
trusted
certificate
authorities
for
the
rest-create/rest-update
methods.
Emails
should
generally
be
secured
using
some
technique
such
as
Direct
.
rest-hook
channels.
A
subscription
is
defined
by
creating
This
specification
describes
three
distinct
outbound
notification
types:
Event
,
Handshake
and
Heartbeat
.
For
each,
the
Subscription
resource
notification
body
is
a
history
Bundle
with
specific
extensions
on
the
server.
When
Bundle.meta
element
to
convey
Subscription
notification
details.
TODO:
In
the
subscription
following
sections
provide
specific
guidance
for
each
channel
types
this
including
for
REST
Hooks
+
Web
Sockets
The
primary
notification
is
created
by
the
client,
it
sets
a
notification
about
an
event.
The
client
expectations
upon
receipt
of
a
Handshake
notification
are
defined
separately
for
each
channel
type
(e.g.,
for
the
status
rest-hook
channel
type,
a
client
endpoint
responds
to
"requested".
After
POSTing
event
notifications
with
standard
HTTP
response
codes).
When
a
connection
to
an
Endpoint
is
established,
the
subscription,
Server
will
send
an
empty
History
Bundle
as
a
Handshake
notification
to
the
client.
The
client
parses
the
Location
header
and
saves
is
not
expected
to
take
any
special
action
in
receipt
of
a
Handshake
notification
beyond
the
new
Subscription's
logical
id
channel-specific
requirement
for
use
in
subsequent
operations.
receiving
an
event
notification.
When
the
server
receives
Servers
MAY
periodically
send
notifications
across
a
subscription,
it
SHOULD
check
that
it
is
prepared
channel
to
accept/process
the
subscription.
If
it
is,
it
sets
ensure
that
the
subscription
to
active
,
connection
is
still
alive
and
then
process
it
like
a
normal
create
.
If
it
isn't,
it
SHOULD
return
an
error
valid
(e.g.,
in
accordance
with
a
client's
requested
heartbat
interval).
The
Heartbeat
notification
is
an
OperationOutcome
instead
of
processing
empty
History
Bundle
sent
without
incrementing
the
create
.
subscription
event
count.
The
criteria
are
subject
client
is
not
expected
to
take
any
special
action
in
receipt
of
a
Heartbeat
notification
beyond
the
same
limitations
as
channel-specific
requirement
for
receiving
an
event
notification.
The
subscription-event-count
extension
indicates
the
client
number
of
unique
events
that
created
it,
such
as
access
have
triggered
notification
attempts
on
this
Subscription
PRIOR
to
patient
compartments
etc.
Note
that
the
subscription
remains
active
after
current
notification
being
sent.
In
the
client
access
tokens
expire.
case
of
a
handshake,
this
count
will
always
be
zero
(0).
Once
In
the
server
has
activated
case
of
a
heartbeat
notification,
this
count
will
be
the
subscription,
it
sets
same
as
the
status
last
notification
and
will
not
be
incremented
due
to
"active"
(note:
the
server
can
do
this
as
it
accepts
the
resource
if
it
wants).
heartbeat
notification.
An
appropriately
authorized
client
can
use
search
and/or
history
operations
to
see
what
subscriptions
are
currently
active
on
In
the
server.
Once
case
of
event
notifications,
the
subscription
is
no
longer
desired,
event
count
will
be
incremented
by
the
number
of
notifications
contained
within
this
bundle
(often
a
single
notification,
though
servers
may
choose
to
batch
notifications
within
a
short
time
interval).
In
the
case
of
an
event
notification
that
cannot
be
delivered
(e.g.,
because
a
client
deletes
endpoint
is
offline),
the
subscription
from
server
MAY
retry
delivery
but
does
not
increment
the
server.
event
count;
the
count
represents
unique
events,
not
unique
delivery
attempts.
The
server
may
retry
bundle-event-count
extension
represents
the
number
of
event
notifications
conveyed
by
the
Bundle.
This
helps
clients:
Determine
if
a
notification
requires
further
processing
(e.g.,
a
fixed
client
might
discard
handshake
and
heartbeat
notifications)
Determine
the
number
of
times
and/or
refer
errors
events
it
should
expeect
to
its
own
alert
logs.
If
find
in
follow-on
queries
when
the
in
empty
payload
type
is
used
Handle
batched
results
(e.g.,
a
server
sending
at
max
one
notification
fails,
per
second)
For
handshake
and
heartbeat
notifications,
the
server
should
set
bundle-event-count
will
alwayhs
be
zero.
The
subscription-status
extension
represents
the
Subscription
status
to
'error'
and
mark
the
error
in
values
at
the
resource.
If
time
the
notification
succeeds,
is
sent.
Note
that
the
server
should
update
status
might
change
between
the
time
the
notification
is
sent
and
the
time
it
is
received/processed,
and
therefore
this
status
recorded
in
the
extension
is
not
guaranteed
to
"active
again.
If
a
subscription
fails
consistently
represent
status
at
the
time
of
receipt.
The
field
is
useful
as
a
hint
to
inform
the
client
if
the
server
may
choose
set
has
encountered
errors
in
notifications
immediately
preceding
this
notification.
The
subscription-topic-url
extension
references
the
subscription
status
Topic
resource
relevant
to
off
and
stop
trying
this
notification,
as
an
absolute
URL
for
the
Topic
resource
on
the
server
that
generated
the
notification
(
NOT
a
reference
to
send
notifications.
a
canonical
Topic
URL.)
If
a
subscription
nominates
a
fixed
end
date,
The
subscription-url
extension
references
the
Subscription
resource
that
triggered
this
notification,
as
an
absolute
URL
for
the
Subscription
resource
on
the
server
automatically
deletes
it
at
that
generated
the
specified
time.
notification.
This
search
will
return
all
the
AuditEvent
resources
that
There
are
about
Patient
three
options
available
when
specifying
the
contents
of
a
Notification:
,103
empty
id-only
,
and
full-resource
.
At
this
time
there
is
no
deterministic
way
to
tell
say
which
of
those
AuditEvent
resources
come
from
These
options
change
the
subscription
sub-system
that
actually
handles
notifications.
This
is
planned
to
be
resolved
in
a
future
version
level
of
this
specification.
In
detail
conveyed
in
the
mean
time,
servers
are
encouraged
notification
Bundle
entries.
When
deciding
which
payload
type
to
create
AuditEvent
records
when
performing
notifications
request,
systems
SHOULD
consider
both
ease
of
processing
and
document
how
clients
can
identify
security
of
PHI.
To
mitigate
the
relevant
records
when
searching.
In
addition,
servers
might
also
create
Communication
resources
for
some
risk
of
information
leakage,
systems
SHOULD
use
the
minimum
level
of
detail
consistent
with
the
notifications
that
are
sent
in
response
to
use
case.
In
practice,
id-only
provides
a
subscription,
such
as
when
sending
emails.
good
balance
for
many
real-world
scenarios.
This
returns
a
list
of
communications
sent
by
a
subscription.
TODO:
search
on
payload....
Examples:
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
.
To
convey
an
event
notification,
the
server
POSTs
to
the
client's
nominated
endpoint
URL
(i.e.
to
the
channel[type=rest-hook].endpoint
)
as
shown
in
the
following
examples.
The
content-type
of
the
POST
SHALL
match
the
contentType
(
channel.payload.contentType
)
requested
during
creation
of
the
Subscription.
Each
channel.header
value
SHALL
be
conveyed
as
an
HTTP
request
header.
For
consistency,
the
rest
of
this
document
assumes
application/fhir+json
has
been
selected,
and
will
be
referred
to
as
JSON.
This
example
uses
an
event
notification
with
an
empty
POST
message
payload
to
alert
the
subscriber
that
new
results
are
available
-
available:
Request:
POST
to
[base]/Subscription:
[client
endpoint]
Request Payload
{
"resourceType": "Subscription",
"criteria": "Observation?name=http://loinc.org|1975-2&_format=json",
"channel": {
"type": "rest-hook",
"endpoint": "https://biliwatch.com/customers/mount-auburn-miu/on-result",
"header": "Authorization: Bearer secret-token-abc-123"
}
}
"resourceType": "Bundle",
"id": "notification-empty",
"meta": {
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-event-count",
"valueDecimal": 1
},
{
"url": "http://hl7.org/fhir/StructureDefinition/bundle-event-count",
"valueUnsignedInt": 1
},
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-status",
"valueCode": "active"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-topic-url",
"valueUrl": "https://example.org/baseR4/Topic/admission"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-url",
"valueUrl": "https://example.org/Subscription/cb2dce51-a1f5-40b4-a98b-c934eae368e8"
}
]
},
"type": "history",
"timestamp": "2019-08-07T10:24:13.1882432-05:00"
}
When
a
resource
Since
the
content
element
is
created
or
updated
that
meets
set
to
empty
,
the
criteria,
data
in
the
server
sends
a
POST
request
with
no
body
to
resources
is
only
available
through
the
nominated
URL.
REST
API,
which
helps
consolidate
authorization
and
authentication
logic.
When
the
subscriber
receives
a
POST
to
https://biliwatch.com/customers/mount-auburn-miu/on-result
,
its
nominated
endpoint
it
re-issues
the
criteria
as
a
might
query
the
server
to
fetch
all
the
server,
appending
relevant
resources
based
on
the
Topic
and
applicable
filters.
The
client
might
include
a
&_since=:last
&_since=
(where
:last
query
parameter,
supplying
its
last
query
timestamp
to
retrieve
only
the
most
recent
resources.
For
example,
the
Topic
above
is
replaced
by
patient
admission,
and
the
time
at
which
subscriber
might
fetch
the
client
last
checked).
most
recent
Encounters
for
a
patient
or
group
of
patients.
In
this
way
it
can
fetch
all
new
relevant
Observations
.
example,
the
event
notification
contains
the
only
the
ids
for
resource.
This
provides
the
subscriber
with
a
resource
ID
for
focused
follow-on
queries.
Request:
POST
to
[client
endpoint]
Request Payload
{
"resourceType": "Bundle",
"id": "notification-id-only",
"meta": {
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-event-count",
"valueDecimal": 2
},
{
"url": "http://hl7.org/fhir/StructureDefinition/bundle-event-count",
"valueUnsignedInt": 1
},
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-status",
"valueCode": "active"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-topic-url",
"valueUrl": "https://example.org/baseR4/Topic/admission"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-url",
"valueUrl": "https://example.org/Subscription/cb2dce51-a1f5-40b4-a98b-c934eae368e8"
}
]
},
"type": "history",
"timestamp": "2019-08-07T10:24:13.1882432-05:00",
"entry": [
{
"fullUrl": "https://example.org/baseR4/Encounter/2",
"request": {
"method": "PUT",
"url": "Encounter/2"
},
"response": {
"status": "201"
}
}
]
}
Since
payload
the
content
element
is
missing,
set
to
id-only
the
data
in
the
resources
is
only
available
through
the
REST
API,
API
which
(as
in
the
empty
payload
example)
helps
consolidate
authorization
and
authentication
logic.
The
server
must
append
the
headers,
if
any
are
given,
to
When
the
subscriber
receives
a
POST
request
that
to
its
nominated
endpoint
it
makes
might
query
the
server
to
fetch
all
the
client.
relevant
resources
using
the
supplied
resource
ids.
For
example,
the
Topic
above
is
patient
admission,
and
the
subscriber
may
fetch
the
Encounter(s)
for
a
patient
or
group
of
patients.
Alternatively,
In
this
example,
the
event
notification
contains
the
server
can
be
asked
to
send
the
entire
resource
to
a
nominated
FHIR
end-point.
resource.
This
is
usually
appropriate
for
defining
routing
rules
within
a
managed
eco-system
ecosystem
such
as
a
healthcare
institution.
Request:
POST
to
[client
endpoint]
Request Payload
{
"channel": {
"type": "rest-hook",
"endpoint": "https://internal.acme.com/research/saturn",
"payload": "application/fhir+json"
}
}
"resourceType": "Bundle",
"id": "notification-full-resource",
"meta": {
"extension": [
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-event-count",
"valueDecimal": 3
},
{
"url": "http://hl7.org/fhir/StructureDefinition/bundle-event-count",
"valueUnsignedInt": 1
},
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-status",
"valueCode": "active"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-topic-url",
"valueUrl": "https://example.org/baseR4/Topic/admission"
},
{
"url": "http://hl7.org/fhir/StructureDefinition/subscription-url",
"valueUrl": "https://example.org/Subscription/cb2dce51-a1f5-40b4-a98b-c934eae368e8"
}
]
},
"type": "history",
"timestamp": "2019-08-07T10:24:13.1882432-05:00",
"entry": [
{
"fullUrl": "https://example.org/baseR4/Encounter/3",
"resource": {
"resourceType": "Encounter",
"id": "3",
"meta": {
"versionId": "1",
"lastUpdated": "2019-08-07T10:49:22Z"
},
"status": "in-progress",
"class": {
"system": "http://terminology.hl7.org/CodeSystem/v3-ActCode",
"code": "VR",
"display": "virtual"
},
"subject": {
"reference": "Patient/123"
}
},
"request": {
"method": "PUT",
"url": "Encounter/3"
},
"response": {
"status": "201"
}
}
]
}
This
requests
that
a
server
forward
a
copy
of
any
matching
resource
in
JSON
format
to
the
nominated
server
as
an
Update
a
create,
update,
or
delete
operation
using
the
nominated
URL
as
the
service
base
.
In
order
to
execute
this
channel,
within
the
server
must
know
how
history
bundle.
Note
that
HTTP
is
not
a
secure
or
encrypted
channel.
It
is
strongly
recommended
that
implementations
refuse
requests
to
authenticate
appropriately
with
the
destination
server.
This
can
be
done
by
the
subscription
resource
providing
an
authentication
header
for
the
server
send
notifications
to
use,
or
alternatively,
URLs
using
the
server
may
be
specifically
configured
HTTP
protocol
(use
HTTPS
instead).
Note
that
HTTP
does
not
provide
endpoint
verification.
It
is
strongly
recommended
that
implementations
refuse
requests
to
be
able
send
notifications
to
use
URLs
using
the
nominated
server.
HTTP
protocol
(use
HTTPS
instead).
Subscriptions are created exclusively via the FHIR REST API. But 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 without polling using the /history operation. This can be accomplished using a websocket notification channel.
A client can declare its intention to listen via Web Sockets:
{
"channel": {
"type": "websocket"
"type": {
"coding": [
{
"system": "http://terminology.hl7.org/CodeSystem/subscription-channel-type",
"code": "websocket"
}
]
}
}
}
}
The subscriber would then initiate a Web Socket connection to the server, at a URL advertised in the FHIR server's Capability statement (subscriptions/webSocketUrl (todo)). A simple protocol is used to listen for notifications:
Trial-Use Note: Warning: The WebSocket channel type is being examined to provide functional parity with other channel types. In particular, the current system fails to address authentication and a desire for multiple subscriptions to be available to a single WebSocket connection. More work is required.
WebSocket security for FHIR Subscriptions is not yet well understood. Implementers should be aware (at minimum) of the following areas:
A client can register for its user to receive notifications by email:
{
"channel": {
"type": "email",
"endpoint": "mailto:mt-auburn-results@direct.biliwatch.com",
"header": "A new bilirubin result has arrived!"
"type": {
"coding": [
{
"system":"http://terminology.hl7.org/CodeSystem/subscription-channel-type",
"code":"email"
}
]
},
"endpoint":"mailto:mt-auburn-results@direct.biliwatch.com",
"payload": {
"contentType": "text/html",
"content": "id-only"
}
}
}
}
The
server
would
will
send
a
new
message
for
each
matching
resource.
The
body
of
the
email
may
be
empty,
or
it
may
contain
server
will
create
a
reference
to
message
based
on
the
search
or
values
present
in
the
matching
resource.
It
is
at
channel.payload.contentType
and
channel.payload.content
fields.
If
a
server
cannot
honor
the
discretion
of
requested
combination,
the
server
as
to
how
much
information
to
provide.
Subscription.channel.header
sets
can
either
reject
the
subject
of
request
or
modify
it
on
creation
to
be
suitable.
In
general,
the
email.
The
email
channel
makes
two
assumptions
about
content:
Because
of
this
context,
the
rules
channel.payload.contentType
primarily
refers
to
the
content
of
the
applicable
jurisdictions.
SMS
works
very
similarly:
body
of
the
message.
Attachment
type
information
can
be
appended
as
a
MIME
parameter,
examples
include:
text/plain
:
a
plain-text
body
with
no
attachment
text/html
:
an
HTML
body
with
no
attachment
text/plain;attach=application/fhir+json
:
a
plain-text
body
with
a
FHIR
JSON
bundle
attached
text/html;attach=application/fhir+xml
:
an
HTML
body
with
a
FHIR
XML
bundle
attached
Note:
SMS
messages
are
extremely
limited
in
size,
so
The
channel.payload
channel.payload.content
will
usually
field
must
be
omitted
(signifying
that
no
payload
is
applied
to
be
sent).
The
recipient
any
attachments,
and
may
be
human,
but
this
is
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
case.
Irrespective
body
of
size,
most
servers
will
refuse
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
send
payloads
empty
.
Trial-Use Note: Warning: The Email/SMS channel types are not yet defined in
SMS for security reasons,a highly standardized way, and mayrefuse to send emails unless encrypted.not be consistently support by servers. More work is required.
A
mime/type
of
text/plain
can
be
useful
for
email
and
sms
along
with
some
extension
describing
how
to
convert
resources
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
text
representation.
This
specification
may
provide
supporting
infrastructure
for
this
in
the
future.
system
such
as
Direct
).
A client can register for its user to receive notifications by messaging :
{
"channel": {
"type": "message",
"endpoint": "http://ehr.example.org/fhir/$process-message"
"type": {
"coding":[
{
"system":"http://terminology.hl7.org/CodeSystem/subscription-channel-type",
"code":"message"
}
]
},
"endpoint":"http://example.org/fhir/base/endpoint/url",
"payload": {
"contentType": "application/fhir+json",
"content": "full-resource"
}
}
}
}
For each matching resource, a server will send a message to the nominated end-point. Most servers will require that the end-point is white-listed prior to allowing these kinds of subscriptions.
Trial-Use Note: Warning: The Messaging channel type is not yet defined in a highly standardized way, and may not be consistently support by servers. More work is required.
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 the (IG?) at (?).
STUTrial-Use Note: Warning: This section is still in early drafting.
At a minimum, the following items should be defined:
channel.type
(e.g.,
'secure-mq'
isntead
of
'channel0012')
channel.endpoint
(e.g.,
URI,
etc.)
channel.header
field
values
(e.g.,
REST-hook
defines
as
Auth
headers
included
in
a
POST)
channel.payload.contentType
(e.g.,
email
defines
this
as
the
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
period.
in
subsequent
operations.
Feedback
When
the
server
receives
a
subscription,
it
SHOULD
check
that
it
is
welcome
here
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.
Servers implementing Subscriptions are responsible for complying with their policies on information logging. Servers are encouraged to track all sent notifications, for example with the use of AuditEvent or Communication resources.
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 | |
|
|
token | The mime-type of the notification payload |
|
|
| status N | token | The current state of the subscription | Subscription.status | |
| type | token | The type of channel for the sent notifications | Subscription.channel.type | |
| url N | uri | The uri that will receive the notifications | Subscription.channel.endpoint |