This
page
is
part
of
the
FHIR
Specification
(v3.0.2:
(v4.0.1:
R4
-
Mixed
Normative
and
STU
3).
)
in
it's
permanent
home
(it
will
always
be
available
at
this
URL).
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
R4
R3
R2
FHIR
Infrastructure
Work
Group
|
Maturity Level : 3 | Trial Use | Security Category : Business | Compartments : Not linked to any defined compartments |
The
subscription
resource
is
used
to
define
a
push
based
push-based
subscription
from
a
server
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
a
message
on
the
defined
"channel"
"channel"
so
that
another
system
is
able
to
can
take
an
appropriate
action.
Once a subscription is created, any newly created or updated resources that meet the criteria in the resource cause a notification to be sent using the provided channel. The criteria are Search strings that have the same interpretation as 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 the resource. The consequence of this is that there is no notification when a resource is deleted, or when a resource is updated so that it no longer meets the criteria.
The server is able to send notifications without any information about the matching resource, or with the entire resource.
Several different types of channels are supported:
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 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
).
Structure
| Name | Flags | Card. | Type |
Description
&
Constraints
|
|---|---|---|---|---|
|
Σ TU | DomainResource |
Elements defined in Ancestors: id , meta , implicitRules , language , text , contained , extension , modifierExtension |
|
|
?! Σ | 1..1 | code |
requested
|
active
|
error
|
off
SubscriptionStatus ( Required ) |
|
Σ | 0..* | ContactPoint |
Contact
details
for
source
(e.g.
troubleshooting)
|
|
Σ | 0..1 | instant | When to automatically delete the subscription |
|
Σ | 1..1 | string | Description of why this subscription was created |
|
Σ | 1..1 | string |
Rule
for
server
push
|
|
Σ | 0..1 | string | Latest error note |
|
Σ | 1..1 | BackboneElement | The channel on which to report matches to the criteria |
|
Σ | 1..1 | code |
rest-hook
|
websocket
|
email
|
sms
|
message
SubscriptionChannelType ( Required ) |
|
Σ | 0..1 |
|
Where the channel points to |
|
Σ | 0..1 |
|
MimeType ( Required ) |
|
Σ | 0..* | string |
Usage
depends
on
the
channel
type
|
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 -->
<<status value="[code]"/><!-- 1..1 requested | active | error | off --> <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]"/><!-- 1..1 Description of why this subscription was created --> <criteria value="[string]"/><!-- 1..1 Rule for server push --> <error value="[string]"/><!-- 0..1 Latest error note --> <channel> <!-- 1..1 The channel on which to report matches to the criteria -->< < < <<type value="[code]"/><!-- 1..1 rest-hook | websocket | email | sms | message --> <endpoint value="[url]"/><!-- 0..1 Where the channel points to --> <payload value="[code]"/><!-- 0..1 MIME type to send, or omit for no payload --> <header value="[string]"/><!-- 0..* Usage depends on the channel type --> </channel><</tag></Subscription>
JSON Template
{
"resourceType" : "",
"resourceType" : "Subscription",
// from Resource: id, meta, implicitRules, and language
// from DomainResource: text, contained, extension, and modifierExtension
"
"
"
"
"
"
"
"
"
"
"
},
"
"status" : "<code>", // R! requested | active | error | off
"contact" : [{ ContactPoint }], // Contact details for source (e.g. troubleshooting)
"end" : "<instant>", // When to automatically delete the subscription
"reason" : "<string>", // R! Description of why this subscription was created
"criteria" : "<string>", // R! Rule for server push
"error" : "<string>", // Latest error note
"channel" : { // R! The channel on which to report matches to the criteria
"type" : "<code>", // R! rest-hook | websocket | email | sms | message
"endpoint" : "<url>", // Where the channel points to
"payload" : "<code>", // MIME type to send, or omit for no payload
"header" : ["<string>"] // Usage depends on the channel type
}
}
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.status [ code ]; # 1..1 requested | active | error | off 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.reason [ string ]; # 1..1 Description of why this subscription was createdfhir:fhir:Subscription.criteria [ string ]; # 1..1 Rule for server push fhir:Subscription.error [ string ]; # 0..1 Latest error note fhir:Subscription.channel [ # 1..1 The channel on which to report matches to the criteria fhir:Subscription.channel.type [ code ]; # 1..1 rest-hook | websocket | email | sms | messagefhir: fhir:fhir:Subscription.channel.endpoint [ url ]; # 0..1 Where the channel points to fhir:Subscription.channel.payload [ code ]; # 0..1 MIME type to send, or omit for no payload fhir:Subscription.channel.header [ string ], ... ; # 0..* Usage depends on the channel type ];fhir:]
Changes
since
DSTU2
R3
| Subscription | |
|
|
|
| Subscription.channel.type |
|
| Subscription.channel.endpoint |
|
|
|
|
| Subscription.tag |
|
See the Full Difference for further information
This analysis is available as XML or JSON .
See
R2
<-->
R3
<-->
R4
Conversion
Maps
(status
=
2
tests
that
all
execute
ok.
All
tests
pass
2
fail
round-trip
testing
and
all
r3
resources
are
valid.).
valid.)
Structure
| Name | Flags | Card. | Type |
Description
&
Constraints
|
|---|---|---|---|---|
|
Σ TU | DomainResource |
Elements defined in Ancestors: id , meta , implicitRules , language , text , contained , extension , modifierExtension |
|
|
?! Σ | 1..1 | code |
requested
|
active
|
error
|
off
SubscriptionStatus ( Required ) |
|
Σ | 0..* | ContactPoint |
Contact
details
for
source
(e.g.
troubleshooting)
|
|
Σ | 0..1 | instant | When to automatically delete the subscription |
|
Σ | 1..1 | string | Description of why this subscription was created |
|
Σ | 1..1 | string |
Rule
for
server
push
|
|
Σ | 0..1 | string | Latest error note |
|
Σ | 1..1 | BackboneElement | The channel on which to report matches to the criteria |
|
Σ | 1..1 | code |
rest-hook
|
websocket
|
email
|
sms
|
message
SubscriptionChannelType ( Required ) |
|
Σ | 0..1 |
|
Where the channel points to |
|
Σ | 0..1 |
|
MimeType ( Required ) |
|
Σ | 0..* | string |
Usage
depends
on
the
channel
type
|
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 -->
<<status value="[code]"/><!-- 1..1 requested | active | error | off --> <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]"/><!-- 1..1 Description of why this subscription was created --> <criteria value="[string]"/><!-- 1..1 Rule for server push --> <error value="[string]"/><!-- 0..1 Latest error note --> <channel> <!-- 1..1 The channel on which to report matches to the criteria -->< < < <<type value="[code]"/><!-- 1..1 rest-hook | websocket | email | sms | message --> <endpoint value="[url]"/><!-- 0..1 Where the channel points to --> <payload value="[code]"/><!-- 0..1 MIME type to send, or omit for no payload --> <header value="[string]"/><!-- 0..* Usage depends on the channel type --> </channel><</tag></Subscription>
JSON Template
{
"resourceType" : "",
"resourceType" : "Subscription",
// from Resource: id, meta, implicitRules, and language
// from DomainResource: text, contained, extension, and modifierExtension
"
"
"
"
"
"
"
"
"
"
"
},
"
"status" : "<code>", // R! requested | active | error | off
"contact" : [{ ContactPoint }], // Contact details for source (e.g. troubleshooting)
"end" : "<instant>", // When to automatically delete the subscription
"reason" : "<string>", // R! Description of why this subscription was created
"criteria" : "<string>", // R! Rule for server push
"error" : "<string>", // Latest error note
"channel" : { // R! The channel on which to report matches to the criteria
"type" : "<code>", // R! rest-hook | websocket | email | sms | message
"endpoint" : "<url>", // Where the channel points to
"payload" : "<code>", // MIME type to send, or omit for no payload
"header" : ["<string>"] // Usage depends on the channel type
}
}
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.status [ code ]; # 1..1 requested | active | error | off 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.reason [ string ]; # 1..1 Description of why this subscription was createdfhir:fhir:Subscription.criteria [ string ]; # 1..1 Rule for server push fhir:Subscription.error [ string ]; # 0..1 Latest error note fhir:Subscription.channel [ # 1..1 The channel on which to report matches to the criteria fhir:Subscription.channel.type [ code ]; # 1..1 rest-hook | websocket | email | sms | messagefhir: fhir:fhir:Subscription.channel.endpoint [ url ]; # 0..1 Where the channel points to fhir:Subscription.channel.payload [ code ]; # 0..1 MIME type to send, or omit for no payload fhir:Subscription.channel.header [ string ], ... ; # 0..* Usage depends on the channel type ];fhir:]
Changes
since
DSTU2
Release
3
| Subscription | |
|
|
|
| Subscription.channel.type |
|
| Subscription.channel.endpoint |
|
|
|
|
| Subscription.tag |
|
See the Full Difference for further information
This analysis is available as XML or JSON .
See
R2
<-->
R3
<-->
R4
Conversion
Maps
(status
=
2
tests
that
all
execute
ok.
All
tests
pass
2
fail
round-trip
testing
and
all
r3
resources
are
valid.).
valid.)
Alternate
See
the
Profiles
&
Extensions
and
the
alternate
definitions:
Master
Definition
(
XML
,
+
JSON
),
,
XML
Schema
/
Schematron
(for
)
+
JSON
Schema
,
ShEx
(for
Turtle
)
+
see
the
extensions
&
the
dependency
analysis
| Path | Definition | Type | Reference |
|---|---|---|---|
| Subscription.status | The status of a subscription. | Required | SubscriptionStatus |
| Subscription.channel.type | The type of method used to execute a subscription. | Required | SubscriptionChannelType |
| Subscription.channel.payload |
|
|
|
Executing
each
of
the
channels
documented
below
involves
the
server
sending
a
communication
that
will
reveal
information
about
the
client
and
server
relationship,
and,
if
the
entire
resource
is
sent,
administrative
or
clinical
information
that
may
be
quite
sensitive
and/or
protected
under
law.
Servers
are
responsible
for
ensuring
appropriate
security
is
employed
for
each
channel.
The
subscription
resource
does
not
address
these
concerns
directly
-
it
is
assumed
that
these
are
administered
by
other
configuration.
configuration
processes.
For
instance,
a
server
might
maintain
a
whitelist
of
acceptable
servers
for
the
rest-create/rest-update
methods.
Emails
should
generally
be
secured
using
some
technique
such
as
Direct
.
A
subscription
is
defined
by
creating
the
Subscription
resource
on
the
server.
When
the
subscription
is
created
by
the
client,
it
sets
the
status
to
"requested".
"requested".
After
POSTing
the
subscription,
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
active
,
and
then
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 remains active after the client access tokens expire.
Once
the
server
has
activated
the
subscription,
it
sets
the
status
to
"active"
"active"
(note:
the
server
can
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',
'error'
and
mark
the
error
in
the
resource.
If
the
notification
succeeds,
the
server
should
update
the
status
to
"active
"active
again.
If
a
subscription
fails
consistently
a
server
may
choose
set
the
subscription
status
to
off,
off
and
stop
trying
to
send
notifications.
If a subscription nominates a fixed end date, the server automatically deletes it at the specified time.
Applications that wish to track whether notifications have been sent for particular resources (or versions of resources) can look at the AuditEvent resources. For example:
GET [base]/AuditEvent?entity=Patient/103
This
search
will
return
all
the
AuditEvent
resources
that
are
about
Patient
103
.
At
this
time
there
is
no
deterministic
way
to
tell
say
which
of
those
AuditEvent
resources
come
from
the
subscription
sub-system
that
actually
handles
notifications.
This
is
planned
to
be
resolved
in
a
future
version
of
this
specification.
In
the
mean
time,
servers
are
encouraged
to
create
AuditEvent
records
when
performing
notifications
and
document
how
clients
can
identify
the
relevant
records
when
searching.
In addition, servers might also create Communication resources for some of the notifications that are sent in response to a subscription, such as when sending emails.
GET [base]/Communication?based-on=Subscription/103
This returns a list of communications sent by a subscription. TODO: search on payload....
This uses an empty POST message to alert the subscriber that new results are available - POST to [base]/Subscription:
{
"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": "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"
}
}
When a resource is created or updated that meets the criteria, the server sends a POST request with no body to the nominated URL.
When
the
subscriber
receives
a
POST
to
https://biliwatch.com/customers/mount-auburn-miu/on-result
,
it
re-issues
the
criteria
as
a
query
to
the
server,
appending
&_since=:last
(where
:last
is
replaced
by
the
time
at
which
the
client
last
checked).
In
this
way
it
can
fetch
all
new
relevant
Observations
.
Since payload is missing, the data in the resources is only available through the REST API, which helps consolidate authorization and authentication logic. The server must append the headers, if any are given, to the POST request that it makes to the client.
Alternatively, the server can be asked to send the entire resource to a nominated FHIR end-point. This is usually appropriate for defining routing rules within a managed eco-system such as a healthcare institution.
{
"channel": {
"type": "rest-hook",
"endpoint": "https://internal.acme.com/research/saturn",
"payload": "application/fhir+json"
"channel": {
"type": "rest-hook",
"endpoint": "https://internal.acme.com/research/saturn",
"payload": "application/fhir+json"
}
}
This requests that a server forward a copy of any matching resource in JSON format to the nominated server as an Update operation using the nominated URL as the service base . In order to execute this channel, the server must know how to authenticate appropriately with the destination server. This can be done by the subscription resource providing an authentication header for the server to use, or alternatively, the server may be specifically configured to be able to use the nominated server.
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"
"channel": {
"type": "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:
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!"
"channel": {
"type": "email",
"endpoint": "mailto:mt-auburn-results@direct.biliwatch.com",
"header": "A new bilirubin result has arrived!"
}
}
The
server
would
send
a
new
message
for
each
matching
resource.
The
body
of
the
email
may
be
empty,
or
it
may
contain
a
reference
to
the
search
or
the
matching
resource.
It
is
at
the
discretion
of
the
server
as
to
how
much
information
to
provide.
Subscription.channel.header
sets
the
subject
of
the
email.
The
email
should
be
secured
appropriately,
such
as
using
Direct,
as
specified
by
the
rules
of
the
applicable
jurisdictions.
SMS works very similarly:
{
"channel": {
"type": "sms",
"endpoint": "tel:+1555-345-5555"
"channel": {
"type": "sms",
"endpoint": "tel:+1555-345-5555"
}
}
Note:
SMS
messages
are
extremely
limited
in
size,
so
payload
should
channel.payload
will
usually
be
set
omitted
(signifying
that
no
payload
is
to
false
be
sent).
The
recipient
may
be
human,
but
this
is
not
always
the
case.
Irrespective
of
size,
most
servers
will
refuse
to
send
payloads
in
SMS
for
security
reasons.
reasons,
and
may
refuse
to
send
emails
unless
encrypted.
A mime/type of text/plain can be useful for email and sms along with some extension describing how to convert resources to a text representation. This specification may provide supporting infrastructure for this in the future.
A client can register for its user to receive notifications by messaging :
{
"channel": {
"type": "message",
"endpoint": "http://ehr.example.org/fhir/$process-message"
"channel": {
"type": "message",
"endpoint": "http://ehr.example.org/fhir/$process-message"
}
}
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.
STU Note: The details of the message - mainly the event code - are still to be resolved during the trial use period.
Feedback is welcome here
.
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 |
|
|
token | Contact details for the subscription | Subscription.contact | |
| criteria | string | The search rules used to determine when to send a notification | Subscription.criteria | |
| payload |
|
The mime-type of the notification payload | Subscription.channel.payload | |
| status | token | The current state of the subscription | Subscription.status | |
| type | token | The type of channel for the sent notifications | Subscription.channel.type | |
| url | uri | The uri that will receive the notifications | Subscription.channel.endpoint |