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
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
© 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:
© 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" } }
}
© 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.
© 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
© 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
© 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
© 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",
© 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
© 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."
}
© 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”
© 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"
}
© 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",
© 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:
© 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”
© 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.
© 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",
© 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
© 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"
}
© 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.