This
page
is
part
of
the
FHIR
Specification
(v3.3.0:
(v3.5.0:
R4
Ballot
2).
#2).
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 : 3 | Ballot Status : Trial Use |
FHIR
Resources
can
be
used
in
a
traditional
messaging
context,
much
like
HL7
v2
(see
detailed
comparison
).
Applications
asserting
conformance
to
this
framework
claim
to
be
conformant
to
"FHIR
messaging"
(see
Conformance
).
In FHIR messaging, a "request message" is sent from a source application to a destination application when an event happens. Events mostly correspond to things that happen in the real world. The request message consists of a Bundle identified by the type "message", with the first resource in the bundle being a MessageHeader resource. The MessageHeader resource has a code - the message event - that identifies the nature of the request message, and it also carries additional request metadata. The other resources in the bundle depend on the type of the request.
The events supported in FHIR, along with the resources that are included in them, are defined below.
The destination application processes the request and returns one or more response messages which are also a bundle of resources identified by the type "message", with the first resource in each bundle being a MessageHeader resource with a response section that reports the outcome of processing the message and any additional response resources required.
This specification assumes that content will be delivered from one application to another by some delivery mechanism, and then one or more responses will be returned to the source application. The exact mechanism of transfer is irrelevant to this specification, but may include file transfer, HTTP based transfer, MLLP (HL7 minimal lower layer protocol), MQ series messaging or anything else. The only requirement for the transfer layer is that requests are sent to a known location and responses are returned to the source of the request. This specification considers the source and destination applications as logical entities, and the mapping from logical source and destination to implementation specific addresses is outside the scope of this specification, though this specification does provide a direct delivery mechanism below.
The agreements around the content of the messages and the behavior of the two applications form the "contract" that describes the exchange. The contract will add regional and local agreements to the rules defined in this specification.
This specification ignores the existence of interface engines and message transfer agents that exist between the source and destination . Either they are transparent to the message/transaction content and irrelevant to this specification, or they are actively involved in manipulating the message content (in particular, the source and destination headers are often changed). If these middleware agents are modifying the message content, then they become responsible for honoring the contract that applies (including applicable profiles) in both directions.
A key aspect of a message is the impact of its content:
| consequence | The message represents/requests a change that should not be processed more than once; e.g., making a booking for an appointment. |
| currency | The message represents a response to query for current information. Retrospective processing is wrong and/or wasteful. |
| notification | The content is not necessarily intended to be current, and it can be reprocessed, though there may be version issues created by processing old notifications. |
Some Events defined by FHIR are assigned to one of these categories, but others are not able to be categorized in advance, and the category must be determined by the content, context, or use case.
When it is necessary to receive an acknowledgement from multiple parties for a message of notification it becomes a message of consequence: The sender will have to send multiple messages, even if they have the same endpoint.
Another key aspect of a message is the impact of its destination.receiver. In some circumstances it may be sufficient to direct a message to an endpoint, while in others it may be necessary to direct the message to a specific organization or person.
| Consequence | A message of consequence SHOULD have one and only one receiver specified. |
| Currency | A message of currency MAY have one or more receivers specified. |
| Notification | A message of currency MAY have one or more receivers specified. |
Each FHIR request message has one or more response messages. There must be at least one response message so that the sender can know that the message was properly received. Multiple response messages SHALL NOT be returned for messages of consequence, and SHOULD not be returned for notifications.
In principle, source applications are not required to wait for a response to a transaction before issuing a new transaction. However, in many cases, the messages in a given stream are dependent on each other, and must be sent and processed in order. In addition, some transfer methods may require sequential delivery of messages.
For
this
reason,
a
synchronous
exchange
pattern
-
where
the
sender
sends
a
message,
and
waits
on
the
same
channel
for
a
single
response,
and
then
sends
the
next
message
-
is
the
easiest
to
understand
and
manage.
The
$process-message
manage:
This kind of messaging exchange is the most common because it's the simplest to understand.
However
synchronous
message
exchange
does
not
cater
for
multiple
response
messages,
which
may
arise
when
processing
queries,
and
also
imposes
through-put
limitations
which
may
become
relevant
at
high
volumes.
Additionally,
it
might
not
be
practical
or
appropriate
to
wait
for
response
messages.
In
these
cases,
the
asynchronous
message
pattern
described
below
should
be
used.
In Asynchronous messaging, the server acknowledges receipt of the message immediately, and responds to the sender separately. The server may respond more than once to any given message.
When a message is received, a receiver can determine from the content of the message header whether it's a new message to process, or a response to a message that has already been sent. Note that asynchronous messaging can be harder to implement due to the amount of complexity opposed to synchronous messaging; more can go wrong. This specification does not dictate any particular error handling protocols or responsibilities; these are left to trading partner agreements between implementers.
An incoming message contains two identifiers: the Bundle.id and the MessageHeader .id. Each time a new message is created, it SHALL be assigned an identifier (MessageHeader.id) that is unique within that message stream. Note that since message streams are often merged with other streams, it is recommended that the identifier should be globally unique. This can be achieved by using a UUID or an OID. Each time a message is sent, the Bundle.id should be changed to a new value.
When a receiver receives and processes the message, it responds with a new message with a new identifier, wrapped in a bundle which also has a new id. The response message also quotes the request MessageHeader.id in MessageHeader.response.identifier so that the source system can relate the response to its request.
A message has 2 important timestamps:
In addition, the message may have additional timestamps in additional resources in the message, either .meta.lastUpdated or others throughout the resources. The meaning of these will depend on the message event.
Some of the message delivery mechanisms mentioned above are reliable delivery systems - the message is always delivered, or an appropriate error is returned to the source. However most implementations use methods which do not provide reliable messaging, and either the request or the response can get lost in transit. FHIR messaging describes a simple approach that receivers SHOULD conform to in order to handle the absence of reliable messaging that maintains predictable functionality.
If
the
sender
of
the
message
implements
reliable
messaging,
it
SHALL
do
the
following
when
it
receives
no
response
to
a
message
within
a
configured
timeout
period
based
on
the
value
specified
in
the
CapabilityStatement
messaging.event.category
for
the
event
associated
with
the
message:
| Consequence | Resend the same message (with the same MessageHeader.id) with the same Bundle.id |
| Currency | Resend the same message (with the same MessageHeader.id) with a different Bundle.id |
| Notification | Resend the same message (with the same MessageHeader.id) with a different Bundle.id |
When a receiver implements reliable messaging, it SHALL check the incoming Bundle.id and MessageHeader.id against a cache of previously received messages. The correct action to take depends on what is received:
| Both the Bundle.id and MessageHeader.id have not been received | This is the normal case, and the message should be processed |
| Both envelope and message already received | The original response has been lost (failed to return to the request issuer), and the original response SHALL be resent |
| The MessageHeader.id has already been received, but the Bundle.id is new | A previously seen message has been resubmitted for processing again. The server may either reprocess the message, or reject the message |
| The Bundle.id has already been received, but the MessageHeader.id is new | This is an error - Bundle.id values should never be reused |
The duration period for caching does generally not need to be very long. At a minimum, it could be 1 minute longer than the timeout of the sending system, though it may need to be longer depending on the re-sending policies of the sending system.
Applications that implement reliable messaging declare their reliable cache period in their Capability Statement .
In the first example, a Clinical EHR issues an order for a particular imaging examination to be performed on a patient. This is considered to be a message of Consequence : multiple orders should not be created (in practice there are usually human review processes that catch multiple orders, but repeat orders create entropy in the system that is harmful). The EHR sends a message where the Bundle.id is UUID 1 (72edc4e0-6708-42ab-9734-f56721882c10), with a MessageHeader.id of UUID 2 (dad53a57-dcb4-4f18-b066-7239eb4b5229).
The EHR system never receives a response to the message; it does not know whether the request message got lost, or the imaging management systems was unable to process the request, or whether it successfully processed the message and the response was lost. In this case, the EHR system resends the message with same two identifiers.
In this case, the imaging system successfully received the message, and processed it. Because it receives the resent order after 1 minute (which is within its 15 minute cache time), and the two UUIDs 1 and 2 match a message it has already processed, it knows that it already processed the order, and simply returns the previous response. In the case of additional resent queries, the application keeps sending the original response, though it may also alert system administrators that the same original message keeps being resent, since lost messages should be a rare occurrence.
When the EHR system finally receives the message, it knows how the imaging management system responded; it can be sure because the message id from the original request is echoed in the response portion of the returned message.
In this second example, a Clinical EHR needs to know what appointment slots are available for a particular imaging procedure. This is a message of Currency : available slots are ever disappearing, and ordering a slot that has become unavailable is a waste of time for the humans and systems involved. The EHR sends a message where the Bundle.id is UUID 3 (4c7f5cb2-5964-4d42-b719-e0227461818c), with a MessageHeader.id is UUID 4 (63ed7d68-b2cc-421d-ba1c-a6c7785581f2).
The EHR system never receives a response to the message; it does not know whether the request message got lost, or the imaging management systems was unable to process the request, or whether it successfully processed the message and the response was lost. In this case, the EHR system resends the message with same MessageHeader.id (UUID 4), but creates a new Bundle.id (c7c17fe4-9560-49c7-b2ae-42636476fb86).
In this case, the imaging system successfully received the message, and processed it. When it receives the resent order after 1 minute (which is within its 15 minute cache time), it sees that although the message id is the same, the Bundle.id has changed, and it reprocesses the message again, and sends a new response.
When the EHR system finally receives the message, it knows the current slot availability on the imaging management system responded.
Note that the existence of active intermediaries (or "middleware") creates the need for this protocol - the original sender matches the response to the request based on the MessageHeader.id, and so an active intermediary that choose the re-initiate a query that it previously relayed cannot change the MessageHeader.id. This protocol avoids the need for the MessageHeader.id to change, and only requires change to the Bundle.id which is never the basis for context linking outside the immediate message exchange protocol described here.
Applications may only assert conformance to "FHIR messaging" if they publish a Capability statement so the claim may be verified. A Capability statement lists all the message events supported (either as sender or receiver) and for each event, a profile that states which resources are bundled (sender), or are required to be bundled (receiver), and any rules about the information content of the individual resources.
The
simplest
way
to
handle
messages
where
there
are
also
RESTful
interactions
occurring
is
to
use
the
$process-message
.
This
operation
accepts
a
message,
processes
it
according
to
the
definition
of
the
event
in
the
message
header,
and
returns
a
one
or
more
response
messages.
For
example,
in
addition
to
processing
the
message
event,
a
server
may
choose
to
retain
all
or
some
the
resources
and
make
them
available
on
a
RESTful
interface,
but
is
not
required
to
do
so.
When
processing
messages,
a
server
may
return
one
of
several
status
codes:
200
OK
:
Indicates
that
the
message
has
been
fully
processed.
If
an
application-level
response
is
expected
for
the
submitted
message,
that
response
SHALL
be
returned
as
the
body
of
the
200
response.
202
Accepted
:
Indicates
that
the
receiving
system
has
accepted
custody
of
the
message
204
No
Content
:
Indicates
that
the
message
has
been
fully
processed
and
would
normally
have
had
an
application-level
response,
but
because
of
instructions
from
the
sender
(e.g.
the
messageheader-response-request
extension),
no
response
is
being
provided
300+
:
Indicates
that
the
message
was
not
successfully
processed.
The
server
MAY
return
an
OperationOutcome
with
additional
information,
and
SHOULD
do
so
if
the
response
code
is
400
or
greater.
The
client
SHALL
interpret
a
4xx
response
to
indicate
that
there
is
no
point
resubmitting
the
unaltered
message,
and
a
5xx
response
to
indicate
an
unexpected
error
occurred
on
the
part
of
the
server,
with
the
implication
that
it
may
be
appropriate
to
resubmit
the
original
message.
Doing
so
SHOULD
NOT
result
in
a
duplicate
message
response.
Repeated
failures
indicate
either
a
fatal
problem
with
the
submission
or
a
problem
with
the
receiving
application.
The
following
rules
apply
when
using
$process-message:
The
operation
only
accepts
POST
transactions
-
any
other
HTTP
method
will
result
in
an
HTTP
error
The
request
content
type
submitted
is
always
a
Bundle
with
type
"message"
containing
a
Message
Header
resource
as
the
first
resource
The
response
content
type
returned
is
always
a
Bundle
with
type
"message"
containing
a
Message
Header
resource
as
the
first
resource,
or
an
HTTP
error
If
the
response
is
an
error,
the
body
SHOULD
be
an
Errors
&
Warning
resource
with
full
details
The
mailbox
may
be
authenticated
using
standard
HTTP
authentication
methods,
including
OAuth
The
$process-message
operation
can
be
used
by
any
HTTP
end-point
that
accepts
FHIR
messages,
not
just
FHIR
RESTful
servers.
In
order
to
ensure
consistency
of
processing,
the
logical
rules
regarding
processing
of
Bundle.id
and
message
id
described
above
SHALL
be
followed
when
messages
are
processed
using
this
operation.
The
$process-message
operation
may
be
used
synchronously,
or
asynchronously.
3.4.3.1
Synchronous
Operation
Synchronous
messaging
is
the
easiest
to
understand;
the
sender
sends
a
message
to
the
receiver
(the
server),
the
server
processes
it,
and
then
returns
a
response.
Usually
(though
not
always)
the
sender
waits
for
the
response
to
the
current
message
before
sending
the
next
message.
This
kind
of
messaging
exchange
is
the
most
common
because
it's
the
simplest
to
understand.
The
following
rules
apply
when
using
the
$process-message
operation
synchronously:
The
URL
(http://server/base/$process-message)
has
no
parameters
It
is
an
error
if
the
sender
POSTs
a
message
that
requires
multiple
response
messages
Servers
SHALL
accept
multiple
concurrent
message
submissions
and
process
them
correctly
(they
are
allowed
to
process
them
sequentially
internally,
but
multiple
concurrent
submissions
is
not
an
error
in
its
own
right)
3.4.3.2
Asynchronous
Operation
In
Asynchronous
messaging,
the
server
acknowledges
receipt
of
the
message
immediately,
and
responds
to
the
sender
separately.
The
server
may
respond
more
than
once
to
any
given
message.
The
following
rules
apply
when
using
the
$process-message
operation
asynchronously:
The
URL
has
at
least
one
parameter:
http://server/base/$process-message?async=true
The
server
acknowledges
the
message
with
a
200
OK
with
no
body,
or
returns
an
HTTP
error
if
the
message
cannot
be
processed.
An
OperationOutcome
SHOULD
be
returned
in
such
a
case
Accepting
the
message
means
that
the
server
has
understood
the
message
enough
to
know
where
to
respond
By
default,
the
server
responds
by
invoking
the
$process-message
using
the
sender's
stated
end-point
in
the
message:
POST
[MessageHeader.source.endpoint]/$process-messages]
Since
the
source
end-point
may
be
manipulated
by
message
transfer
engines,
an
alternative
response
address
may
be
specified
using
the
parameter
"response-url":
http://server/base/$process-message?async=true&response-url=http://server2.com/base/anything.
The
endpoint
at
the
specified
URL
SHALL
implement
the
signature
of
the
$process-message
operation
(parameter
async=true,
accept
a
Bundle,
return
a
200
OK
or
an
error)
The
server
submits
response
messages
to
the
appropriate
end-point
with
See
the
parameter
async=true.
There
is
no
response
message
opreation
definition
for
the
response
messages
When
a
message
is
received,
a
receiver
can
determine
from
the
content
of
the
message
header
whether
it's
a
new
message
to
process,
or
a
response
to
a
message
that
has
already
been
sent.
Note
that
asynchronous
messaging
can
be
harder
to
implement
due
to
the
amount
of
complexity
opposed
to
synchronous
messaging;
more
can
go
wrong.
This
specification
does
not
dictate
any
particular
error
handling
protocols
or
responsibilities;
these
are
left
to
trading
partner
agreements
between
implementers.
further
details.
As well as this messaging framework documented here, FHIR also defines a RESTful API . The messaging and RESTful frameworks are related in that both share the same set of resources on which they operate. In fact, the basic MessageHeader resource that the messaging framework is implemented is itself a resource that can treated in a RESTful approach.
The kinds of functionality that the RESTful API and the messaging framework offer are very similar; their primary difference is architectural in nature.
For instance, the messaging framework defines an event for notifying that an administration resource has been created or updated; the REST API offers similar services ( history and Subscription ). On the other hand, there are differences in the capabilities offered - while a patient merge can be implemented as a series of RESTful operations performed by the client that update all resources linked to the patient, when a message command to merge patient records is processed, the server will do all the work, and is also able to merge in areas not exposed on the RESTful API. The REST API, however, provides a set of basic operations on all resources that would need special definitions in the messaging framework - definitions that are not provided.
There is no expectation that RESTful systems will need to offer messaging support, or vice versa, though systems may find it useful to support both sets of functionality in order to satisfy a wider range of implementers.
As a resource that can be used with the RESTful framework, the MessageHeader resource has the normal resource end-point (/MessageHeader), which is used to manage a set of static message resources. This could be used to make an archive of past messages available. Creating or updating MessageHeader resources in this fashion does not represent the actual occurrence of any event, nor can it trigger any logic associated with the actual event. It is just for managing a set of message header resources.
It is possible to exchange messages using the RESTful end-point as a central point of exchange. This is not particularly efficient compared to other methods, but is useful for low-volume asynchronous exchange.
To send a message, a sender posts the message bundle to the /Bundle end-point, with a uri that identifies the receiver at MessageHeader.destination.endpoint . The RESTful server accepts the bundle, stores it as a single bundle, and indexes it on the MessageHeader .
To receive messages, a receiver searches for all messages destined for itself, since its last check:
GET [base]/Bundle?message.destination-uri=[rcv]&_lastUpdated=>2015-03-01T02:00:02+01:00
The receiver works through the response, processing each message. As each message is processed, the receiver creates a response message, reversing the source and destination, and posts it back to the server.
To check for responses, the original sender searches for response messages destined for itself, since its last check:
GET [base]/Bundle?message.destination-uri=[snd]&message.response-id:missing=false
&_lastUpdated=>2015-03-03T06:03:522+01:00
This lightweight protocol needs ongoing administration to ensure that multiple parties do not interfere with each other by re-using the same system identifier (and against malicious attack).
The
message.code
element
carries
a
Coding
that
identifies
the
event
that
the
message
conveys.
This
table
lists
the
message
event
codes
defined
in
this
specification
(the
system
value
for
these
is
"
http://hl7.org/fhir/message-events
"):
Code
Category
Description
Request
Resources
Response
Resources
Notes
The
request
and
response
details:
The
column
values
are
either
a
resource
that
is
included
as
part
of
the
response,
or
an
element
that
refers
to
another
resource,
which
means
that
the
target
of
these
references
SHALL
also
be
in
the
message.
In
this
table,
the
request
and
response
columns
list
the
focus
resource
for
the
event,
along
with
other
resources
that
should
also
be
carried
in
the
message
directly
(if
they
exist).
Additional
events
Events
may
be
defined
using
the
MessageDefinition
resource.
This
specification
does
not
define
any
events,
but
may
do
so
in
the
future
if
implementers
find
this
useful.
A message can be used to invoke an operation as defined for a RESTful interface using an operation definition. To invoke an operation using a message:
urn:ietf:rfc:3986
OperationDefinition.url
MessageHeader.data
refers
to
a
Parameters
resource
The recipient executes the operation as specified, and then:
MessageHeader.data
refers
to
a
Parameters
resource
Here's an example:
<Bundle xmlns="http://hl7.org/fhir">
<id value="urn:uuid:77831928-2a35-4c08-9496-8232323bf48c"/>
<!-- normal bundle stuff -->
<entry>
<fullUrl value="urn:uuid:6080d4a7-5e05-45dc-96d5-f75329564d1f"/>
<resource>
<MessageHeader>
<id value="cac8143e-6138-4f45-b086-bb8ebf976aae">
<!-- normal message header stuff -->
<event>
<system value="urn:ietf:rfc:3986"/>
<!-- value set expansion -->
<code value="http://hl7.org/fhir/OperationDefinition/ValueSet-expand"/>
</event>
<!-- more normal message header stuff -->
<data>
<reference value="urn:uuid:00213637-dc7c-40d2-a7de-f4ef1eea5685"/>
</data>
</MessageHeader>
</resource>
</entry>
<entry>
<fullUrl value="urn:uuid:00213637-dc7c-40d2-a7de-f4ef1eea5685"/>
<resource>
<Parameters>
<parameter>
<name value="identifier"/>
<valueUri value="http://hl7.org/fhir/ValueSet/identifier-type"/>
</parameter>
</Parameters>
</resource>
</entry>
</Bundle>
Note that there's no way to anchor the execution of the operation against a URL. The only operations that can be executed in this way are defined to be executed at the System or Resource level for a particular resource.
In the same way that a defined operation can be invoked, a regular search operation can be invoked. This also uses the Parameters resource, with the following rules:
| Search Parameter Type | Data Type |
| number | integer |
| date | dateTime |
| string | string |
| token | string or Coding (split the system and code apart) |
| reference | uri |
| composite | string |
| quantity | string or Quantity (split the syntax out) |
| uri | uri |
Here's an example:
<Bundle xmlns="http://hl7.org/fhir">
<id value="urn:uuid:77831928-2a35-4c08-9496-8232323bf48c"/>
<!-- normal bundle stuff -->
<entry>
<fullUrl value="urn:uuid:c466754c-09c0-4f59-9f76-a48bd0ea27c9"/>
<resource>
<MessageHeader>
<!-- normal message header stuff -->
<event>
<system value="http://hl7.org/fhir/restful-interaction"/>
<!-- Search against Patient -->
<code value="search-type"/>
</event>
<!-- more normal message header stuff -->
<data>
<reference value="urn:uuid:59a17a19-46eb-42d9-821a-f93a0c530cac"/>
</data>
</MessageHeader>
</resource>
</entry>
<entry>
<fullUrl value="urn:uuid:59a17a19-46eb-42d9-821a-f93a0c530cac"/>
<resource>
<Parameters>
<parameter>
<name value="resourceType"/>
<valueString value="Patient"/>
</parameter>
<parameter>
<name value="gender"/>
<valueString value="m"/>
</parameter>
</Parameters>
</resource>
</entry>
</Bundle>