the subspace communication framework - open.epic

21
Epic | 1979 Milky Way | Verona WI 53593 | Voice: 608.271.9000 | Fax: 608.271.7237 | www.epic.com The Subspace Communication Framework Last Reviewed: 04/15/2022

Upload: others

Post on 17-Jun-2022

6 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: The Subspace Communication Framework - open.epic

Epic | 1979 Milky Way | Verona WI 53593 | Voice: 608.271.9000 | Fax: 608.271.7237 | www.epic.com

The Subspace

Communication

Framework

Last Reviewed: 04/15/2022

Page 2: The Subspace Communication Framework - open.epic

Introduction .................................................................................................................................................... 3

Design Overview .............................................................................................................................. 3

The FHIRcast Model ........................................................................................................................ 3

Initialization Sequence .................................................................................................................................. 3

1. Session Discovery ................................................................................................................... 3

2. OAuth Authorization ............................................................................................................ 7

3. The Subscription Handshake ............................................................................................. 12

Message Passing .......................................................................................................................................... 16

To Hyperdrive ................................................................................................................................ 16

From Hyperdrive ........................................................................................................................... 18

Optional Workflows ................................................................................................................................. 19

Subspace Configuration ................................................................................................................ 19

Page 3: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 3

Introduction The Subspace Communication Framework (Subspace, for short) serves as the Hyperdrive replacement for

the COM-based integration patterns that EDManager and PatientAgent provided for the native Windows

Hyperspace application and as a base for other client integrations with Hyperdrive. This document outlines

the steps that an external application must take to initiate and communicate via a Subspace integration with

Hyperdrive.

This document does not provide details for how any integration functions once it is initiated, beyond a

general format of communication between Hyperdrive and the external application.

Design Overview

Subspace is a pattern for asynchronous, asymmetric, semi-event-driven integrations between Hyperdrive

and external applications. The pattern follows these general steps:

1. An external application discovers the URL for a local HTTP server at which Hyperdrive is listening and a

unique identifier for Hyperdrive.

2. The application obtains an access token associated with permissions to send and/or receive certain events

to and/or from Hyperdrive.

3. Using the information obtained in the previous two steps, the application initiates a subscription

handshake over HTTPS and Secure WebSockets (WSS) with Hyperdrive’s Subspace server.

4. After the handshake is complete, Hyperdrive and the application pass messages over HTTPS (messages

to Hyperdrive) and WSS (messages from Hyperdrive).

The FHIRcast Model

Subspace is based off the STU2 FHIRcast Spec. We recommend that any developer wishing to integrate with

Hyperdrive via Subspace familiarize themselves with FHIRcast.

In FHIRcast, there is a single “hub” (Hyperdrive) and any number of “subscribers” (external applications).

Subscribers send subscription requests to the hub for events for which the hub dispatches notifications

during relevant workflows. When the hub dispatches a notification for an event, all subscribers subscribed to

that event will receive the notification.

Subscribers may also communicate to the hub directly through requests to change context. In response to

these requests, the hub may or may not dispatch one or more event notifications that will go out to all

appropriate subscribers, informing them of the change in context.

As an implementation of FHIRcast, Subspace supports all the events in the FHIRcast event catalog. However,

not all the events that Subspace supports are part of FHIRcast. For Epic-specific events, please refer to the

relevant Epic-provided specs for the event’s integration details and how they might differ from FHIRcast’s

specifications.

Initialization Sequence

1. Session Discovery

To communicate with Hyperdrive via Subspace, an external application must discover the following pieces

of information:

Page 4: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 4

• Hub URL – the URL at which Hyperdrive’s Subspace server is listening

• Hub Topic – a unique identifier for this instance of Hyperdrive

Any application can do this by running the Hyperdrive Launcher, although some integrations provide other

mechanisms for session discovery. Those other mechanisms, if they exist for your integration, are covered in

your integration’s spec document.

Hyperdrive Launcher

The Hyperdrive Launcher is an executable named “Launcher.exe” that is installed with Hyperdrive. The

Hyperdrive Launcher can find existing instances of Hyperdrive that are running on the user’s workstation or

launch new ones connected to a given environment. It is designed specifically to be called by external

applications to facilitate a Subspace integration.

Finding the Launcher

The Hyperdrive Launcher is found within the directory of the local Hyperdrive install. You can determine

this location by reading the “InstallLocation” string value of the

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Hyperdrive

registry key.

From there, the Launcher.exe executable can be found in {Install Location}\VersionIndependent.

For example, a standard Hyperdrive install will have an Install Location of “C:\Program Files

(x86)\Epic\Hyperdrive” and the Launcher.exe executable can be found in “C:\Program Files

(x86)\Epic\Hyperdrive\VersionIndependent”.

Launcher.exe must run from the VersionIndependent sub-directory of the Hyperdrive install or it will not

function correctly.

Prerequisites

To use the Hyperdrive Launcher, you must know the Organization ID and the Environment Name for an

Epic environment to which you would like Hyperdrive to be connected.

Organization Ids and Environment Names are derived from the config files in {Install Location}\Config. Each

config file corresponds to a single Organization ID which is the prefix for the file. For example,

861Config.json corresponds to the Organization ID 861.

Each config file contains any number of environments defined under the “Environments” node. The

Environment Name of an environment is the name of the node representing the environment. For example,

consider the following contents of 861Config.json:

{ "OrganizationName": "Epic Medical Center", "Environments": { "PROD": { "DisplayName": "Production Environment", "HSWebServerURL": "https://epic.example.com/PRODUCTION" } "SUPPORT": { "DisplayName": "Support Environment", "HSWebServerURL": "https://epic.example.com/SUPPORT" } }

}

Page 5: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 5

The names for the environments for this file would be “PROD” and “SUPPORT.”

Input

Arguments are passed to the Launcher.exe executable via the command line. Each argument must be of the

form “<KEY>=<VALUE>”

Key Optionality Value

id Required* a valid Organization ID

env Required* a valid Environment Name

tz Optional a valid time zone identifier from the tz database e.g., “America/Chicago”

mode Optional “Auto”, “Find”, “FindAll”, or “Launch” (defaults to “Auto”)

*unless “mode=FindAll” is passed as well, see discussion in the following section about expected behavior

Behavior

If “mode=Auto” is passed or the “mode” parameter is not passed at all, the Hyperdrive Launcher (referred

to as “launcher” below) will first check to see if there are any running Hyperdrive instances connected to the

environment with the passed Organization ID and Environment Name (which uniquely identify an

environment).

If the launcher discovers such a Hyperdrive instance, it will communicate the details of the instance back to

the caller of the executable via standard out (see the Output section below).

If the launcher does not discover an appropriate Hyperdrive instance, it will attempt to launch a new

Hyperdrive instance connected to the environment with the passed Organization Id and Environment. Once

the launched Hyperdrive instance has successfully connected to its environment, the launcher will

communicate the details of the instance back to the caller of the executable via standard out (see the Output

section below).

If the “tz” parameter is passed to the launcher, the launcher will launch or find a Hyperdrive that is both

connected to the appropriate environment AND operating in the indicated time zone.

If “mode=Find” is passed to the launcher, the launcher will only look for existing Hyperdrive instances

connected to the appropriate environment and time zone (if applicable) and return the details of the first

instance it finds.

If “mode=FindAll” is passed to the launcher, the launcher will only look for existing Hyperdrive instances

connected to the appropriate environment and time zone (if either are applicable) and return the details of all

instances it finds. Note: if using this mode, the “id” and “env” parameters are optional, except that if passing

an “env” parameter, you must also pass an “id” parameter.

If “mode=Launch” is passed to the launcher, the launcher will skip looking for existing Hyperdrive instances

and will always launch a new Hyperdrive.

Output

The Hyperdrive Launcher communicates results via exit codes and standard out.

Here is a list of the possible exit codes. Any exit code other than 0 is considered a failure.

Page 6: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 6

Code Meaning

0 Success

1 The Hyperdrive Launcher encountered an unknown error.

2 Invalid arguments passed to the Hyperdrive Launcher.

3 The Hyperdrive Launcher launched a new Hyperdrive instance but timed out while waiting for

communication.

4 The Hyperdrive Launcher attempted to launch a new Hyperdrive instance but encountered a

process creation failure.

5 The Hyperdrive Launcher launched a new Hyperdrive instance, but the new instance was unable

to communicate back to the launcher correctly.

6 The Hyperdrive Launcher attempted to launch a new Hyperdrive instance, but the passed

Organization ID and Environment could not be resolved to a valid, available environment. Or, if a

time zone identifier was passed, the environment found could not support the indicated time zone.

7 The Hyperdrive Launcher attempted to launch a new Hyperdrive instance, but the new instance

could not connect to the specified environment.

8 The Hyperdrive Launcher attempted to launch a new Hyperdrive instance, but the new instance

could not correctly set up its Subspace web server.

If the exit code for the Hyperdrive Launcher is 0, it will also write an object to standard out in JSON as

follows:

{ "url": "https://127.0.0.1:55502/IcZuv0qNo06XftQYWc-H3g", "topic": "873njwe98-oo-0", "environment": "prod", "customerId": "861", "timezone": "America/Chicago", "isNew": true

}

If “mode=Find” is passed to the Hyperdrive Launcher and no running Hyperdrive instance was found, the

object will be empty.

If “mode=FindAll” is passed to the Hyperdrive Launcher, the output will be a JSON array of objects

conforming to the above pattern. If no instances were found an empty JSON array will be returned (although

the exit code of the launcher will still be 0).

A non-empty object representing a Hyperdrive instance contains the following properties:

Property Name Value

url Hub URL

Page 7: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 7

topic Hub Topic

environment Environment Name of the environment to which Hyperdrive is connected; should

match the value of the “env” parameter passed to the Hyperdrive Launcher

customerId Organization ID of the environment to which Hyperdrive is connected; should match

the value of the “id” parameter passed to the Hyperdrive Launcher

timezone Time zone identifier for the time zone in which the Hyperdrive instance’s is operating;

should match the value of the “tz” parameter passed to the Hyperdrive Launcher, if one

was passed

isNew true, if the current invocation of the Hyperdrive Launcher started this instance of

Hyperdrive

2. OAuth Authorization

Subspace enforces access through OAuth 2.0 authorization. As such, to initialize a Subspace integration, an

external application must use a valid OAuth 2.0 access token associated with one or more scopes

corresponding to Subspace events for which they have registered.

An access token may either be retrieved directly through Subspace as described below (see Retrieving an

Access Token) or received as part of another mechanism specific to your integration. If going through

Subspace directly, you will need to perform a one-time dynamic registration of a client for an install of your

application (see Dynamic Client Registration). Other mechanisms for retrieving an access token, if they exist,

are covered in your integration’s spec document.

Registering for Subspace Scopes

To receive an OAuth 2.0 access token, an organization must first register for a static Client ID and one or

more Subspace scopes with Epic. You initiate this process by contacting open.epic and by asking for a

Subspace-enabled Client ID. Note that each application will be provisioned two static Client IDs, one for

production environments and one for non-production environments. If necessary, at run-time an application

can discover to which type of environment Subspace is connected via the Subspace Configuration Endpoint

(see section below).

To contact open.epic for a client ID, follow the steps under the Web Services section of open.epic. If you

require changes to a released client ID, for example adding or removing scopes to an existing client ID, a new

client ID will be issued.

As part of the registration process, you will be asked for a list of scopes to be associated with your Client ID.

Subspace scopes are strings that follow a set syntax: <prefix>/<event name>.<permission>

Scope “part” Value

prefix fhircast – if the event is defined in the FHIRcast specification

epic – if the event is a custom event defined for Epic integrations

event name the identifier for this “type” of event e.g., Patient-open or com.epic.userlogin

Page 8: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 8

permission read – if the scope allows your application to receive the event from Hyperdrive

write – if the scope allows your application to send the event to Hyperdrive

Example scopes:

fhircast/Patient-open.read

fhircast/Patient-open.write

epic/com.epic.userlogin.read

Retrieving an Access Token

To retrieve an access token directly from Hyperdrive, an application must first discover Hyperdrive’s Hub

URL (see Session Discovery section).

The application then sends an HTTP POST request to <Hub URL>/token. The POST request’s body should be

application/x-www-form-urlencoded content with the following required parameters (see RFC 6749 section

4.4.2 and RFC 7523 section 2.2 for background):

Parameter Name Value

grant_type client_credentials

client_assertion_type urn:ietf:params:oauth:client-assertion-type:jwt-bearer

client_assertion a Javascript Web Token (JWT) to be used to authenticate the client

Example Access Token Request:

POST https://127.0.0.1:55502/IcZuv0qNo06XftQYWc-H3g/token Content-Type: application/x-www-form-urlencoded

grant_type=client_credentials& client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer& client_assertion=eyJhbGciOiJSUz...epMGtDXNnicvLacYepAKA

The client_assertion JWT should have the following claims:

Identifier Value

iss the application’s Client ID (either static or dynamic)

sub the application’s Client ID (either static or dynamic)

aud a URI unique to the environment to which Hyperdrive is connected. There are several

acceptable values for this parameter, one of them is discoverable via the Subspace

Configuration Endpoint (see section below).

exp a UTC timestamp for when the JWT should expire (should be less than 5 minutes)

jti a nonce for protecting against replay attacks

Page 9: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 9

The JWT should be signed with the cryptographic private key corresponding to the public key associated

with the Client ID that is being used as iss/sub (either static or dynamic). Subspace only accepts JWTs signed

using the RSA SHA-384 signing algorithm.

Example JWT head (pre-encoding):

{ "alg": "RS384", "typ": "JWT"

}

Example JWT body (pre-encoding):

{ "iss": "G27841966-407A-11EB-B087-460231621F93", "sub": "G27841966-407A-11EB-B087-460231621F93", "aud": " urn:example:cec.prd", "exp": "1611585885", "jti": "c5evjdku.ov1"

}

If the request and JWT are valid and Hyperdrive can validate the signature of the JWT using the public key

on file for the Client ID in the JWT, the Subspace server will respond with a 200 OK response whose body

contains a JSON object with the following properties:

Property Name Value

access_token a valid access token to be used with Subspace integration

token_type “bearer”

expires_in the number of seconds for which the access token remains valid

scope If the “iss” Client ID used was dynamic

a comma-delimited list of scope strings, some or all of which correspond to

permissions for Subspace events (other kinds of scopes may be associated with the

Client ID)

each Subspace scope string takes the form <prefix>/<event-name>.<read/write> where

• <prefix> is either “fhircast” (for FHIRcast standard events) or “epic” (for Epic

custom events)

• <event-name> is the unique string used to identify that event

• <read/write> indicates whether this scope corresponds to receive (“read”) or

send (“write”) the event

If the “iss” Client ID used was static

“system/DynamicClient.register” which indicates this token can only be used to

dynamically register a client (see Dynamic Client Registration)

Example:

{ "access_token": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3", "token_type": "bearer",

Page 10: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 10

"expires_in": 3600, "scope": "fhircast/Patient-open.read,fhircast/Patient-open.write,

epic/com.epic.shutdown.read" }

If the request or JWT was invalid or Hyperdrive could not validate the signature on the JWT, the Subspace

server will respond with a 4XX response whose body will contain a JSON object with following properties:

Property Name Value

error a short string identifying the general type of error

error_description a more specific error message

Example:

{ "error": "INVALID-CLIENT", "error_description": "Client id not recognized." }

Dynamic Client Registration

The first time an install of an application wishes to integrate with Subspace and begin retrieving access

tokens directly, it must first dynamically register itself as a client. To dynamically register a client, an

application must have

1. Registered a static Client ID (otherwise known as a Software ID) (see Registering for Subspace Scopes)

2. Used its static Client ID to retrieve an access token that can be used to dynamically register a client (see

Retrieving an Access Token)

The application then sends an HTTP POST request to <Hub URL>/register.

The POST must have the following headers:

Header Name Value

Content-Type “application/json”

Authorization “Bearer <ACCESS-TOKEN>” where <ACCESS-TOKEN> is the access token that can

be used to dynamically register a client

The POST request’s body must be a JSON object with the following properties:

Property Name Value

jwks a JSON Web Key Set (JWKS) containing an RSA public key to be associated with a new

dynamic client

software_id the application’s static Client ID (otherwise known as a Software ID)

Example:

POST https://127.0.0.1:55502/IcZuv0qNo06XftQYWc-H3g/register Authorization: Bearer i8hweunweunweofiwweoijewiwe

Page 11: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 11

Content-Type: application/json {

"jwks": { "keys": [ { "e": "AQAB",

"n":"kWp2zRA23Z3vTL4uoe8kTFptxBVFunIoP4t_8TDYJrOb7D1iZNDXVeEsYKp6ppmrTZDAg-cNOTKLd4M39WJc5FN0maTAVKJc7NxklDeKc4dMe1BGvTZNG4MpWBo-taKULlYUu0ltYJuLzOjIrTHfarucrGoRWqM0sl3z2-fv9k",

"kty": "RSA", "kid": "1b94c" } ] },

"software_id": "46fc7afe-d33b-4e78-9bc4-50af04fb0211","

}

If the request is valid, the access token has the appropriate permissions, and Hyperdrive recognizes the static

Client ID, the Subspace server will respond with a 200 OK response whose body contains a JSON object with

the following property:

Property Name Value

client_id the Client ID of a newly associated dynamic client whose public key is the one

provided in the dynamic client registration request and whose Subspace permissions

match those registered with the original static client.

Example:

{ "client_id": " G27841966-407A-11EB-B087-460231621F93" }

If the request was invalid, Hyperdrive did not recognize the static Client ID, or the static Client ID was not

authorized for dynamic client registration, the Subspace server will respond with a 4XX response whose

body will contain a JSON object with following properties:

Property Name Value

error a short string identifying the general type of error

error_description a more specific error message

Example:

{ "error": "INVALID-TOKEN”

"error_description": "Access token cannot be used for dynamic client registration."

}

Page 12: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 12

3. The Subscription Handshake

To initiate a Subspace integration with Hyperdrive, an external application must successfully complete a

Subscription Handshake, pictured below:

Prerequisites

To be able to initiate and successfully complete Subspace’s Subscription Handshake, an external application

must have the following pieces of information:

• Hub URL – the URL at which Hyperdrive’s Subspace server is listening

• Hub Topic – a unique identifier for this instance of Hyperdrive

• Access Token – an OAuth 2.0 access token linked to permissions for Subspace events

For more information on how to obtain Hyperdrive’s Hub URL and Hub Topic, refer to the Session

Discovery section above.

For more information on how to obtain an Access Token, refer to the OAuth Authorization section above.

Basic Handshake

Sending HTTP Request

The application sends an HTTP Post request to Hyperdrive’s Hub URL.

The POST must have the following headers:

Header Name Value

Content-Type “application/x-www-form-urlencoded”

Page 13: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 13

Authorization “Bearer <ACCESS-TOKEN>” where <ACCESS-TOKEN> is the OAuth 2.0 access

token mentioned in the OAuth Authorization section.

The POST form body can also have the following key-value pairs:

Key Value

hub.topic Hyperdrive’s Hub Topic

hub.mode “subscribe”

hub.events a comma-delimited listed of event names to which to subscribe

hub.channel.type “websocket”

Subspace does not support the FHIRcast optional value “webhook” for the

“hub.channel.type” key-value pair. If “webhook” is sent instead of “websocket,” the

handshake will fail.

Subspace does not support the optional FHIRcast key “hub.lease_seconds.” If included, the value will be

ignored.

Example Request:

POST https://127.0.0.1:55502/IcZuv0qNo06XftQYWc-H3g Authorization: Bearer i8hweunweunweofiwweoijewiwe Content-Type: application/x-www-form-urlencoded

hub.topic=fdb2f928-5546-4f52-87a0-0648e9ded065& hub.mode=subscribe& hub.events=patient-open,com.epic.shutdown& hub.channel.type=websocket

Receiving HTTP Response

If the application’s HTTP request is missing the Authorization header, the Subspace server will respond with

401 Unauthorized and the handshake will fail.

If the application’s HTTP request body is missing any values or one of the values is invalid, the Subspace

server will respond with 400 Bad Request and the handshake will fail.

If the application’s HTTP request body contains a “hub.topic” value that does not match the Hub Topic for

Hyperdrive, the Subspace server will respond with 400 Bad Request and the handshake will fail.

Otherwise, the Subspace server will respond with 202 Accepted and the body of the response will contain a

JSON object with a single property, “hub.channel.endpoint”, whose value will be a WSS endpoint string.

Example Accepted Response

HTTP/1.1 202 Accepted

{ "hub.channel.endpoint": "wss://subspace.example.com/ee30d3b9-1558-464f-a299-

cbad6f8135de"

}

Page 14: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 14

Connecting to WebSocket

If the Subspace server responded with 202 Accepted to the application’s HTTP request, the application

creates a WSS connection with the Subspace server by connecting to the endpoint received in the Subspace

server’s response body.

If the application fails to connect or never connects to the WebSocket, the handshake fails.

Receiving WSS Result

Once the Subspace server receives the application’s WSS connection, it will send a serialized JSON object

representing the final result of the application’s subscription request. The object will have the following

properties:

Property Name Value

hub.mode either “subscribe” or “denied”

hub.topic the Hyperdrive instance’s Hub Topic

hub.events a comma-delimited list of events to which the application attempted to subscribe

hub.lease_seconds the number of seconds for which the subscription is valid (only present if

hub.mode is “subscribe”)

hub.reason a string message explaining why the subscription was denied (only present if

hub.mode is “denied”)

If the “hub.mode” property is “subscribe”, the handshake has completed successfully, and the application

can begin sending messages to and receiving messages from Subspace (see the Message Passing section).

If the “hub.mode” property is “denied”, the handshake fails. A subscription may be denied at this stage for

the following reasons:

• The access token passed in the original request was not recognized by Hyperdrive

• The access token passed in the original request was expired

• The access token passed in the original request was not associated with appropriate scopes for one or

more of the asked-for events.

Example Success Response

{ "hub.mode": "subscribe", "hub.topic": "fdb2f928-5546-4f52-87a0-0648e9ded065", "hub.events": "patient-open,com.epic.shutdown", "hub.lease-seconds": 7200 }

Example Failure Response

{ "hub.mode": "denied", "hub.topic": "fba7b1e2-53e9-40aa-883a-2af57ab4e2c", "hub.events": "patient-open,patient-close,com.epic.shutdown",

Page 15: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 15

"hub.reason": "Subscriber does not have valid authorization for one or more requested events."

}

Variations

Re-Subscription

If an application wishes to change their subscription to Subspace events, they may do so by initiating another

Subscription Handshake with the Subspace server. To reuse an existing endpoint, the application must add a

“hub.channel.endpoint” key-value pair to its initial HTTP request body. The value for this parameter

specifies the endpoint to be reused.

The rest of the handshake is the same, with the WSS result being sent through WebSocket as soon as the

result can be determined, since the application has already connected in a previous subscription.

If the endpoint passed with the HTTP request is not an endpoint associated with an existing, unexpired

subscription, the re-subscription will be denied.

Sending a valid re-subscription replaces any original subscription associated with the access token and

endpoint pairing used. If re-subscription is denied for any reason, the original subscription will remain

unaffected.

Example re-subscription request:

POST https://127.0.0.1:55502/IcZuv0qNo06XftQYWc-H3g Authorization: Bearer i8hweunweunweofiwweoijewiwe Content-Type: application/x-www-form-urlencoded

hub.topic=fdb2f928-5546-4f52-87a0-0648e9ded065& hub.mode=subscribe& hub.events=patient-open,patient-close,com.epic.shutdown& hub.channel.type=websocket& hub.channel.endpoint=wss%3A%2F%2Fsubspace.example.com%2Fsession%2Fws%2Fv7tfwuk17a

Un-Subscription

If an application wishes to unsubscribe from all events associated with their access token and endpoint

pairing, they may do so by initiating another Subscription Handshake with Subspace server. However, in the

initial request the value of the “hub.mode” key-value pair must be “unsubscribe” instead of “subscribe”.

Additionally, the request should not include the “hub.events” key-value pair and should add a

“hub.channel.endpoint” key-value pair to its initial HTTP request body. The value for

“hub.channel.endpoint” parameter should be the endpoint used for the subscription.

The rest of the handshake is the same, with the WSS result being sent through WebSocket as soon as the

result can be determined, since the application has already connected in a previous subscription.

If the endpoint passed with the HTTP request is not an endpoint associated with an existing, unexpired

subscription, the un-subscription will be denied.

Sending a valid un-subscription removes any original subscription associated with the access token and

endpoint pairing used. It also closes the WebSocket connection, meaning the endpoint cannot be used for re-

subscription in the future. If un-subscription is denied for any reason, the original subscription and

connection will remain unaffected.

Example un-subscription request:

Page 16: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 16

POST https://127.0.0.1:55502/IcZuv0qNo06XftQYWc-H3g Authorization: Bearer i8hweunweunweofiwweoijewiwe Content-Type: application/x-www-form-urlencoded

hub.topic=fdb2f928-5546-4f52-87a0-0648e9ded065& hub.mode=unsubscribe& hub.channel.type=websocket& hub.channel.endpoint=wss%3A%2F%2Fsubspace.example.com%2Fsession%2Fws%2Fv7tfwuk17a

Subscription/Token Expiration & Revocation

When a subscription and/or access token associated with a subscription expires, the Subspace server will

send a subscription denial message via the open WSS connection. The denial message will be sent when

Hyperdrive recognizes that a subscription/token is expired, which may not be immediately after the

expiration happens. This may also happen if the access token used to subscribe gets revoked for any reason.

Once the denial message is sent to the application, the subscription is considered canceled, and a new

Subscription Handshake must be completed to restart the integration. The endpoint from the original

subscription may not be reused.

Example expiration message:

{ "hub.mode": "denied", "hub.topic": "fba7b1e2-53e9-40aa-883a-2af57ab4e2c", "hub.events": "patient-open,patient-close,com.epic.shutdown",

"hub.reason": "Access token has expired." }

Message Passing Once a Subspace integration has been initialized, the integration is mediated through messages passed over

HTTPS and WSS. Each message is associated with a particular event (e.g., closing a patient’s chart) that is

identified by an event name (e.g., “Patient-close”). Messages sent to Hyperdrive are generally requests for an

event to occur. Messages from Hyperdrive are generally notifications that an event has occurred.

These semantics vary event-by-event and integration-by-integration; refer to your integration’s spec

document for details.

To Hyperdrive

A message sent to Hyperdrive via Subspace is called a Request for Context Change (RCC) per the FHIRcast

pattern.

RCCs are sent over HTTPS to Hyperdrive’s Subspace server.

Sending HTTP Request

To send an RCC to Hyperdrive, an application sends an HTTP POST request to Hyperdrive’s Hub URL with

the following headers:

Header Name Value

Content-Type “application/json”

Page 17: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 17

Authorization “Bearer <ACCESS-TOKEN>” where <ACCESS-TOKEN> is the OAuth 2.0 access

token mentioned above.

The body of the request is a JSON object with the following properties:

Property Name Value

id a unique identifier for this event notification

timestamp a UTC timestamp for when the event notification was sent out

event a JSON object describing the event. See the “event” property description below

The “event” property has the following properties:

Property Name Value

hub.topic Hyperdrive’s Hub Topic

hub.event the event name for the event which for which the request was sent

context varies event-by-event; refer to your integration’s spec document for details

Example Request:

POST https://127.0.0.1:55502/IcZuv0qNo06XftQYWc-H3g Authorization: Bearer i8hweunweunweofiwweoijewiwe Content-Type: application/json

{

"timestamp": "2018-01-08T01:37:05.14", "id": "q9v3jubddqt63n1", "event": { "hub.topic": "fdb2f928-5546-4f52-87a0-0648e9ded065", "hub.event": "patient-close", "context": [ { "key": "patient", "resource": { "resourceType": "patient-close", "id": "ewUbXT9RWEbSj5wPEdgRaBw3", //...other properties... } ] }

}

Receiving HTTP Response

If the access token sent with the request is not associated with an unexpired subscription to the relevant

event OR the subscription does not have “write” permission for the event, the Subspace server responds

with 401 Unauthorized.

If the HTTP request is malformed in any way, the Subspace Server responds with 400 Bad Request.

Page 18: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 18

If there are other event-specific issues with the request, the Subspace Server responds with 400 Bad Request;

refer to your integration’s spec document for details.

Otherwise, if the request is accepted and will be processed, the Subspace server responds with 202 Accepted.

A 202 Accepted result only indicates that the RCC could be processed, not that any action will be

performed in response to it. Refer to your integration’s spec document for details on any further responses

you can expect from Hyperdrive in response to an RCC for a specific event.

From Hyperdrive

A message received from Hyperdrive via Subspace is called an Event Notification.

Event Notifications are sent over WSS to an application subscribed to an event.

Receiving WSS Message

An event notification is sent via a WebSocket message to an application only if that application has an open

connection associated with an unexpired subscription for the relevant event AND that subscription has

“read” permission for the event.

The notification is sent as a JSON object with the following properties:

Property Name Value

id unique identifier for this event notification

timestamp a UTC timestamp describing the time at which the event occurred

event a JSON object describing the event. See below.

The “event” property has the following properties:

Property Name Value

hub.topic Hyperdrive’s Hub Topic

hub.event the event name for the event which prompted this notification

context varies event-by-event; refer to your integration’s spec document for details.

Example Notification:

{ "timestamp": "2018-01-08T01:37:05.14", "id": "q9v3jubddqt63n1", "event": { "hub.topic": "fdb2f928-5546-4f52-87a0-0648e9ded065", "hub.event": "patient-close", "context": [ { "key": "patient", "resource": {

"resourceType": "patient-close", "id": "ewUbXT9RWEbSj5wPEdgRaBw3",

Page 19: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 19

//...other properties... }

} ] }

}

Sending WSS Response

When an application receives an Event Notification, the application sends a confirmation via a WSS message.

The message contains a single JSON object with the following properties:

Property Name Value

id the identifier for the received event notification

status a numeric HTTP status code indicating the success (2XX) or failure of the event

notification (4XX-5XX)

If a subscriber would like the option to send a follow-up syncerror in response to an event notification from

Subspace, they must send a status of 202 in their WSS response to that event notification.

Example:

{ "id": "q9v3jubddqt63n1", "status": "202"

}

Optional Workflows

Subspace Configuration

At run-time, applications may make GET queries to the <Hub URL>/subspace-configuration to discover

certain configuration parameters associated with the current Subspace session. All values are reported as

strings in a simple JSON object.

A subscriber may optionally include an Epic-Client-ID header whose value is the static client ID for their

application. When this header is included in the request, Subspace will include additional client-specific

configuration parameters in the response object.

The current configuration parameters reported in the HTTP response are as follows, but more may be added

in the future:

Parameter Name Requires Client

ID Header?

Value

isProduction No 1 if Subspace is connected to a production environment, 0

otherwise

Page 20: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 20

audience No a URN uniquely identifying the environment to which

Subspace is connected, usable as the “aud” claim in JWTs used

in access token requests (see section above)

fhirServerUrl Yes the base URL at which the client should make FHIR web

service requests

interconnectBaseUrl Yes the base URL at which the client should make non-FHIR

Interconnect web service requests

hyperspaceVersion No the Hyperspace web version (for telemetry purposes only)

hyperdriveVersion No the Hyperdrive host version (for telemetry purposes only)

Example Configuration Request (without Client ID header):

GET https://127.0.0.1:55502/IcZuv0qNo06XftQYWc-H3g/subspace-configuration

Example Response:

{ "isProduction": "0", "audience": "urn:oid:fhir", "hyperspaceVersion": "10.1.0.0", "hyperdriveVersion": "100.2.0.1642"

}

Example Configuration Request (with Client ID header):

GET https://127.0.0.1:55502/IcZuv0qNo06XftQYWc-H3g/subspace-configuration Epic-Client-ID: 46fc7afe-d33b-4e78-9bc4-50af04fb0211

Example Response:

{ "isProduction": "0", "audience": "urn:oid:fhir", "fhirServerUrl": "https://fhir.epic.com/interconnect-fhir-oauth/api/FHIR/R4", "interconnectBaseUrl": "https://fhir.epic.com/interconnect-fhir-oauth", "hyperspaceVersion": "10.1.0.0", "hyperdriveVersion": "100.2.0.1642"

}

Page 21: The Subspace Communication Framework - open.epic

© 2022 Epic Systems Corporation. 21

© 2022 Epic Systems Corporation. All rights reserved. PROPRIETARY INFORMATION - This item and its contents may not be accessed, used, modified,

reproduced, performed, displayed, distributed, or disclosed unless and only to the extent expressly authorized by an agreement with Epic. This item is

a Commercial Item, as that term is defined at 48 C.F.R. Sec. 2.101. It contains trade secrets and commercial information that are confidential, privileged

and exempt from disclosure under the Freedom of Information Act and prohibited from disclosure under the Trade Secrets Act. After Visit Summary,

Analyst, App Orchard, ASAP, Beacon, Beaker, BedTime, Bones, Break-the-Glass, Bugsy, Caboodle, Cadence, Canto, Care Everywhere, Charge Router,

Chronicles, Clarity, Cogito ergo sum, Cohort, Colleague, Comfort, Community Connect, Cosmos, Cupid, Epic, EpicCare, EpicCare Link, Epicenter, Epic

Earth, EpicLink, EpicWeb, Garden Plot, Good Better Best, Grand Central, Haiku, Happy Together, Healthy Planet, Hyperspace, Kaleidoscope, Kit,

Limerick, Lucy, Lumens, MyChart, OpTime, OutReach, Patients Like Mine, Phoenix, Powered by Epic, Prelude, Radar, Radiant, Resolute, Revenue

Guardian, Rover, Share Everywhere, SmartForms, Sonnet, Stork, System Pulse, Tapestry, Trove, Welcome, Willow, Wisdom, With the Patient at Heart,

and WorldWise are registered trademarks, trademarks, or service marks of Epic Systems Corporation in the United States of America and/or other

countries. Other company, product, and service names referenced herein may be trademarks or service marks of their respective owners. Patents

Notice: www.epic.com/patents.