Da Vinci Health Record Exchange (HRex)
1.0.0 - STU R1 United States of America flag

Da Vinci Health Record Exchange (HRex), published by HL7 International - Clinical Interoperability Council. This is not an authorized publication; it is the continuous build for version 1.0.0). This version is based on the current content of https://github.com/HL7/davinci-ehrx/ and changes regularly. See the Directory of published versions

Exchanges allowing human intervention

Page standards status: Informative

This page covers the mechanisms for requesting data when there is a potential for humans to be involved in the process of finding, organizing, filtering, and/or reviewing the data shared prior to exchange. Guidance on whether these 'request' mechanisms are appropriate is found here and guidance for choosing between the CommunicationRequest and Task approaches can be found here.

Note: This page focuses on the use of standard RESTful mechanisms to drive fulfillment of a CommunicationRequest or Task. It is also possible to use asynchronous custom operations or asynchronous messaging. Either of these mechanisms would need to be invoked in asynchronous mode. Both approaches require more negotiation/custom development than a pure REST solution, though they may align better with traditional application architectures and in some environments may be simpler overall. Guidance on choosing between messaging and operations can be found here.

Requesting exchange using CommunicationRequest

The basics of this mechanism are that a formal CommunicationRequest - generally with a focus of 'order' - is created that defines the data to be shared and who it is to be shared with. For the purposes of this documentation, the focus is on the system requesting the data and receiving the data being the same (the data consumer), however it is possible - and in fact common - for this mechanism to be used when the data is to flow to a different party. I.e. party A (the requester) authorizes the data source to transmit a specified set of data to a third-party data consumer.

In FHIR, a request resources represent plans, proposals or orders (authorizations) for actions to occur. However, they do not, by themselves, directly solicit action. Some sort of process must occur that triggers a solicitation for the 'request' to be fulfilled. There are numerous mechanisms in FHIR for seeking such fulfillment - all described in the FHIR core specification section on workflow communication patterns. The following diagrams and descriptions summarize the key steps in each flow and some of the considerations associated with each of the options.

Direct POST, both ways

In this approach, the CommunicationRequest soliciting data is posted directly to the data source's system and the resulting data is POSTed directly back to the data consumer's system. While lighter-weight than some of the alternatives below, it requires that records be created on the RESTful endpoints of both data source and data consumer that might not actually be desired and does not give the data consumer much choice as to what happens to the data when received - it must either be stored as a record on the respective endpoint or it must be thrown away. (This also means that the data consumer must have an endpoint for the desired data to be stored on.) This mechanism provides no mechanism to track status of work in progress. A refusal is represented by a Communication instance indicating that no Communication happened.

Balloter feedback requested: Given the downsides associated with this approach to exchange, should it be listed as one of the options in this document?

This approach corresponds to Option A in the FHIR core workflow communication patterns.

Data ConsumerData Sourceopt1.POST 'placer order'CommunicationRequest [cr1]2.POST 'filler order'CommunicationRequest3.POST [requested data]opt4.POST Communication (referencing [cr1] and [requested data])

Step 1: When creating an order, the authoritative copy of it *should* be kept on the system responsible for creating it, as that is the system that has authority to make decisions about status changes, etc. The CommunicationRequest sent to the data source should be a copy with intent of 'filler-order' that references the original data consumer-maintained original 'placer-order'.

Step 2: A copy of the CommunicationRequest (or possibly the only electronic record of the order) is created on the data source's system with a 'tag' indicating that the recipient is being asked to fulfill the order. This tag is essential to differentiate a CommunicationRequest to be acted upon from one provided as a 'for your information'.

Step 3: In this option, the data is POSTed directly back to the data consumer. This may not be appropriate in all cases as it may not make sense for the data consumer to expose a RESTful endpoint and it may not want to persist the full set of data sent.

Step 4: While the data has been delivered, nothing indicates to data consumer that the request is complete. As well, it is possible there is no data available or that the request has been refused. Posting the Communication resource allows closing this loop. However, closing the loop by formally creating a Communication instance as part of the patient record is not necessarily always appropriate. (Such resources will rarely be created for data shared by the data consumer directly querying the data source's system.

CommunicationRequest plus Task

This approach uses Task to seek fulfillment of the CommunicationRequest. It eliminates the need for Communication to link together the data returned. It also allows explicit monitoring of the state (e.g. acceptance/rejection, progress) prior to completion. Note that this flow is similar to the Task-only flow described below, with the primary difference being that it uses a formal CommunicationRequest 'order' to define the data requested rather than just using the Task itself.

This approach aligns with Option G in the FHIR core workflow communication patterns, where the Task is posted directly to the filler's system (data source). Alternate workflows using Task where the Task lives on the placer's system (data consumer) - Option F or on an intermediary system Option H, however those require either polling or subscription by the data source. In general these alternatives would only make sense if the request for information wasn't directed to a specific data source (which would be unusual) or if the data consumer did not have authority to post a Task directly to the data source's system.

Data ConsumerData Source1.POST 'placer order' CommunicationRequest [cr1]2.POST Task [t1] with focus [cr1]3a.GET (read) [cr1] based on reference from Task [t1]3b.Return [cr1] (instructing on what data to retrieve)opt4.PUT Task [t1]update status5.Poll/Subscribe to see [t1] status6.POST [requested data]7.PUT Task [t1]link to [requested data]8.Poll/Subscribe to see [t1] statusopt9a.Query to retrieve [requested data] based on reference from [t1]9b.Query response containing [requested data]

Step 1: The authoritative CommunicationRequest is created on the data consumer's system. (It is possible later, after receiving the Task, that the data source might create a 'filler' CommunicationRequest, but there would be no need to exchange it and it would have no impact on the workflow.)

Step 2: The Task is posted directly to the data source by the data consumer, initiating fulfillment of the CommunicationRequest. The CommunicationRequest is the 'focus' of the Task.

Step 3: The data source reads the CommunicationRequest (that was referenced by the Task) from the data consumer to determine what data is needed.

Step 4: The data source may optionally update the Task to change the status (e.g. from requested to accepted or rejected and eventually to in-progress or on-hold. The data source might also update the Task.businessStatus element to convey additional information around progress, such as reasons for delay or expected timeframe for delivery.

Step 5: In order for the data consumer to receive information about changes to the Task status, it would either need to poll the Task by periodically performing a read on the Task instance or create a Subscription on the data source so that it is notified when the Task is updated. (Note that it will have to use one of these approaches even if not interested in status changes as polling must be used in Step 7 to see that the Task is complete.

Step 6: In this option, instead of being directly POSTed directly back to the data consumer, the requested data record(s) are instead stored on the data source's system. This step is marked as 'optional' because in some cases the requested data might already exist on the source system and there will be no need to create it. As for step 3 above, multiple resource instances may need to exist to satisfy the communication request. It is possible that some may need to be created, while others may be pre-existing. In principle, any resources created due to the CommunicationRequest could potentially be available for subsequent query by other systems. Also, it is also possible that the created records might exist on a system other than the data source.

Step 7: The data source updates the Task to reference the resources created and/or identified in step 5 as Task.output values and sets the Task status to completed. (It is possible that outputs may be added over time through multiple updates before the Task is marked as complete. If this happens, it is up to the data consumer whether to retrieve outputs as they are added or to wait until the Task is complete.)

Step 8: The data consumer retrieves the completed Task from the data source using either polling or a previously created Subscription. Note that this can be combined with Step 9 below if the polling or subscription mechanism makes use of _include to retrieve the Task.output references at the same time as the Task is returned. (Note that there is currently no standard search parameter to support such an _include.)

Steps 9: Once the data consumer has the Task and knows what data is deemed to satisfy the request (based on references in Task.output), it can then directly query that information - either as individual reads, as a query by resource id(s) or by a batch of queries or reads. This step can be omitted if the outputs are retrieved as part of the polling/subscription in Step 8.

NOTE: Both this approach and the following one can make use of both Task and a Request. In this first approach, the Task has a 'focus' of the CommunicationRequest. It describes the information to be retrieved and the Task is saying "please fulfill the order". In the Task-based approach that follows, the Task describes what information is to be retrieved. It *may* refer to a Request that is being fulfilled in whole or in part by the Task and which provides an authorization for the information to be retrieved.

Requesting exchange using Task

In this approach, no CommunicationRequest is used at all - as there is no need for a formal order. Instead, the Task itself describes the data to be retrieved. The workflow is identical to that used in CommunicationRequest plus Task, except that the first step (the creation of the CommunicationRequest) and the third step (read of the CommunicationRequest) are skipped and the Task transmitted in the initial step does not specify a Task.focus.

Data ConsumerData Source1.POST Task [t1] (self-describing desired data)opt2.PUT Task [t1]update status3.Poll/Subscribe to see [t1] status4.POST [requested data]5.PUT Task [t1]link to [requested data]6.Poll/Subscribe to see [t1] statusopt7a.Query to retrieve [requested data] based on reference from [t1]7b.Query response containing [requested data]

Step 1: The Task is posted directly to the data source by the data consumer. The Task describes the data to be provided directly.

Step 2: The data source may optionally update the Task to change the status (e.g. from requested to accepted or rejected and eventually to in-progress or on-hold. The data source might also update the Task.businessStatus element to convey additional information around progress, such as reasons for delay or expected timeframe for delivery.

Step 3: In order for the data consumer to receive information about changes to the Task status, it would either need to poll the Task by periodically performing a read on the Task instance or create a Subscription on the data source so that it is notified when the Task is updated. (Note that it will have to use one of these approaches even if not interested in status changes as polling must be used in Step 7 to see that the Task is complete.

Step 4: The data source creates and/or locates the desired records on its system.

Step 5: The data source updates the Task to reference the resources created and/or identified in step 5 as Task.output values and sets the Task status to completed. (It is possible that outputs may be added over time through multiple updates before the Task is marked as complete. If this happens, it is up to the data consumer whether to retrieve outputs as they are added or to wait until the Task is complete.)

Step 6: The data consumer retrieves the completed Task from the data source using either polling or a previously created Subscription. Note that this can be combined with Step 7 below if the polling or subscription mechanism makes use of _include to retrieve the Task.output references at the same time as the Task is returned. (Note that there is currently no standard search parameter to support such an _include.)

Steps 7: The data consumer then retrieves the resources referenced by Task.output. This step can be omitted if the outputs are retrieved as part of the polling/subscription in Step 6.


Additional Da Vinci-specific guidance on using Tasks for information retrieval can be found here