Getting Started Subscribing to state updates can be done either by using a websocket connection provided by realtime API or by using a notification channel created using this API. Consuming state updates consists of these 3 steps: Create a session Connect to the WebSocket address given in the session response or use your notification channel Add subscriptions to the session in order to receive real time state updates Step One: Creating a Session In order to use the Real Time API, you must first create a session. Sessions are long lived, survive WebSocket disconnections, and allow you to subscribe to real time state updates. We recommend one session in case of WebSockets for each unique user in your application. Sessions expire after a period of inactivity. In this situation, you must create a new session and resubscribe. Note There is a limit restriction on how many active sessions can be alive per user (active session here means an open session with an active websocket connection or an alive notification channel). This limit for a single user is 30, after which we respond with 400 Bad Request. Using a Websocket Connection The following example request creates a new session using a new websocket connection. Request curl 'https://realtime.jive.com/v2/session' -X POST -H 'Authorization: Bearer {ACCESS_TOKEN}' As shown below, the response contains a JSON structure with three fields related to the session. Response { "self" : "https://realtime.jive.com/v2/session/4m1egos8MCo3Ia46nJxWFaLOz4eKM6V3", "ws" : "wss://realtime.jive.com/ws/v2/4m1egos8MCo3Ia46nJxWFaLOz4eKM6V3", "subscriptions" : "https://realtime.jive.com/v2/session/4m1egos8MCo3Ia46nJxWFaLOz4eKM6V3/subscriptions" } self: a reference to the created session ws: a reference to the WebSocket used to receive real time state updates subscriptions: a reference to the resource used for managing subscriptions within the session Using a Notification Channel The following example request creates a new session using a notification channel. For creating the channel, you can use this API. A channel must be created with a lifetime of maximum 7 days, otherwise the Realtime API will reject session creation. In that case Realtime will return 400 with the errorCode equals to CHANNEL_LIFETIME_TOO_LONG. The ID of the notification channel received in the response when creating the notification channel should be included in the request body of the Realtime session creation request as the channelId. You must use the same user and client to create the notification channel and the realtime session. If we detect a mismatch, the API will return 403 with the errorCode equals to OWNER_MISMATCH. This channelId needs to be unique to this session, and will serve as the ID of the session. If this endpoint is called with a channelId that is already in use, the API will return 409 with the errorCode equals to UNIQUE_CHANNEL_ID. The session's lifetime is connected to the notification channel's lifetime. As long as you don't let your notification channel expire, your session will exist. We suggest you create your notification channel with a lifetime of 7 days and refresh it every day using this endpoint, as long as you wish to receive events on that channel. Important: If you are using a webhook type notification channel, we are expecting a response from your URL in less than 2 seconds. After a response indicating success (with HTTP 200), or after the given 2 seconds elapses, we will continue to send subsequent messages in the queue. Note that if you are taking significantly longer to process each event, we cannot guarantee that the messages will be delivered to you in the order they were generated. Request curl 'https://realtime.jive.com/v2/session' -X POST -H 'Authorization: Bearer {ACCESS_TOKEN}' -H 'Content-Type: application/json' -d '{"channelId": "{CHANNEL_ID}}"} As shown below, the response contains a JSON structure with two fields related to the session. Response { "self" : "https://realtime.jive.com/v2/session/{CHANNEL_ID}", "subscriptions" : "https://realtime.jive.com/v2/session/{CHANNEL_ID}/subscriptions" } self: a reference to the created session subscriptions: a reference to the resource used for managing subscriptions within the session To check the status of a session, send a GET request to the URL in the self field above. curl 'https://realtime.jive.com/v2/session/4m1egos8MCo3Ia46nJxWFaLOz4eKM6V3' -H 'Authorization: Bearer {ACCESS_TOKEN}' Step Two: Open a WebSocket or Use Your Notification Channel Using the Websocket Provided by Realtime API Now that you have an active session, it is time to open a WebSocket connection to the WebSocket address specified in the session creation response under ws in preparation to receive data for the subscriptions you will make in step 3. Note that you can also open the WebSocket or disconnect and reconnect the WebSocket after creating subscriptions. You can use your favorite WebSocket testing tool to complete this step. If you don't have a tool, we recommend trying Simple WebSocket Client for Google Chrome for an up and running in 60 seconds or less experience. Whatever tool you choose, enter the WebSocket URL from the ws in the session creation response. We only support one connection to the WebSocket per session. Additional connections terminate the existing connection. Websocket Error Codes In case the WebSocket connection gets closed by our end, your application would receive one of the following codes: 3000 internal error: failed to send keepalive or ping message, or pong message did not received in a timely manner. 3100 invalid frame type: in case text or binary message received from client. 4000 session not found: client tried to connect to a Session that does not exist 4001 session replaced: a new WebSocket connection is opened on the same session Using a Notification Channel If you created your session using a notification channel, you can access it based on the documentation of the notifications api Step Three: Subscribe Now that you have an active session and a way to receive real time state updates, you can create a subscription via a POST request to the URL returned in the subscriptions field of the session creation response. The Real Time API creates a subscription using the parameters passed in the request. The account and id parameters can be found by using the Users API (organization.id and id respectively). The other parameters are hardcoded for now: Subscription type should always be dialog Entity type should always be line.v2. When you create a subscription you must pass in a unique name as the id parameter. This name will be passed back in the events received on the websocket and can be used to identify to which subscription this event belongs to in your application. In the example below the subscription ID is “elisha”. Subscription ID must be unique, and can not be used multiple times. Request curl 'https://realtime.jive.com/v2/session/4m1egos8MCo3Ia46nJxWFaLOz4eKM6V3/subscriptions' -X POST -H 'Authorization: Bearer {ACCESS_TOKEN}' -H 'Content-Type: application/json' \ -d '[ { "id":"elisha", "type":"dialog", "entity": { "id":"99be59bc-edfc-4c62-a73f-06087ec2fe00", "type":"line.v2", "account":"f9d449ad-99b6-4105-985a-399cb1b29c41" } } ]' As shown below, the returned response contains the requested subscription ids as field names with their values being either true or false depending on whether or not the subscription was successful. If the request contained multiple subscriptions, the response contains a key value pair for each requested subscription. Response { "elisha": true } Note: when using a Notification Channel sometimes you will get a response code 202 Accepted without response body. This means that Realtime API couldn't process your request immediately, but your subscriptions will be created in a short while, typically within a few seconds. You can check your subscriptions by querying your session. Subscription Types Dialog The dialog subscription type allows you to subscribe to call state information for a single line. The subscription takes the following form in which the entity.type value must be line.v2 the entity.id value must be the ID of a line to which the requesting user has permissions to subscribe the entity.account value must be the organization ID of the organization to which the line specified by entity.id belongs. { "id":"elisha", "type":"dialog", "entity": { "id":"99be59bc-edfc-4c62-a73f-06087ec2fe00", "type":"line.v2", "account":"f9d449ad-99b6-4105-985a-399cb1b29c41" } } The resulting messages received over the WebSocket contain the following structure: legId the unique ID for this call state snapshot, related to the line on a particular device. In case you have multiple devices on the same line (eg. a soft-phone, and a hard-phone), you would receive multiple events with different legId. If the originatorId is the same for both events, they belong to the same call. type the type of the event either announce, replace, withdraw and keepalive. See more details below with examples. direction a representing the role of the line in the call represented by this state snapshot. Valid values are: recipient the line used to create the subscription received an incoming call initiator the line used to create the subscription placed an outgoung call created the Unix timestamp, in ms, at which the call reflected by this state snapshot was created ani the origination telephone number. This is the first number the call was made to. The field is populated when the call hits a call queue. The ANI is not related to the caller ID such as call display. This field is useful for tracking the number the caller originally called, regardless of transfers and other call changes - allows you to correlate incoming calls to marketing campaigns with a specific phone number for example. state the current state of the call from a telephony standpoint. Note that more than one BRIDGED <-> UNBRIDGED cycles are possible. Valid values are: CREATED - event that is produced when a new leg is created. RINGING - event that is produced when a leg begins ringing. ANSWERED - event that is produced when a leg gets answered. BRIDGED - event that is produced when a leg gets connected to something. UNBRIDGED - event that is produced when a leg gets disconnected from something. HUNGUP - event that is produced when an existing leg gets destroyed. callee - identity of the entity receiving the call. name - name of the callee. number - number of the callee. caller - identity of the entity making the call. name - name of the caller. number - number of the caller. That might be a phone number or an extension number. participant - address of record (SIP username) isClickToCall - boolean value, true if the call was initiated by Click-to-Call flow, false otherwise originatorId - unique id of the entity that triggered the creation of this leg Example Data for line.v2 Subscription Type You receive real time state updates upon creation of a new subscription. Each state update is a self contained snapshot of the state of the resource represented by the subscription that generated the update. While sending complete state snapshots is less efficient than sending deltas, the client side logic to manage state updates and synchronization can be greatly simplified by working only with complete state snapshots. The Real Time API uses four message types over the WebSocket and three types over the notification channel. Let's list them. Important: When using a notification channel, these messages will be in the content field of the message received on the notification channel. You can find more information about the exact payload in the description of the Notification Channel createChannel method. Here is an example of such message: { "source": "realtime-api", "type": "line.v2", "timestamp": "2021-08-26T11:13:42.397946Z", "ttl": 3600, "content": "{SEE_MESSAGE_CONTENT_BELOW}", "bypassDoNotDisturb": false } Announce This message indicates that a subscription resulted in a a new state snapshot previously unknown to the current connection. Also, upon disconnection and reconnection, the last relevant state will be published using this state. The following example represents a snapshot of call state generated from the subscription with ID elisha. { "type": "announce", "subId": "elisha", "entityId": "9d", "data": { "legId": "dcfb5e21-e2f7-430c-b07c-c0ed0f114a60-1582109247.16853", "created": 1490792855704, "participant": "4YEnv05UehWIMwNrHz0tQVVksALmci", "direction": "recipient", "state": "CREATED", "callee": { "name": "John Doe", "number": "1015" }, "caller": { "name": "Ronnie O'Sullivan", "number": "1000" }, "isClickToCall": false, "originatorId": "a40ad185-9e94-454b-a57a-b52ae6029ba6" } } Replace This message indicates a new state snapshot for a resource known to the current connection. The update references a previously received oldId and assigns the state a new ID via newId. These IDs correspond to IDs provided in previously received announce/replace messages as entityId/newId. { "type": "replace", "subId": "elisha", "oldId": "9d", "newId": "9e", "data": { "legId": "dcfb5e21-e2f7-430c-b07c-c0ed0f114a60-1582109247.16853", "created": 1490792855704, "participant": "4YEnv05UehWIMwNrHz0tQVVksALmci", "callee": { "name": "John Doe", "number": "1015" }, "caller": { "name": "Ronnie O'Sullivan", "number": "1000" }, "direction": "recipient", "state": "RINGING", "isClickToCall": false, "originatorId": "a40ad185-9e94-454b-a57a-b52ae6029ba6" } } Withdraw This message indicates that the state of the resource has been destroyed. You will no longer see updates for this resource via replace messages. { "type": "withdraw", "subId": "elisha", "entityId": "9e", "data": { "legId": "dcfb5e21-e2f7-430c-b07c-c0ed0f114a60-1582109247.16853", "created": 1490792855704, "participant": "4YEnv05UehWIMwNrHz0tQVVksALmci", "callee": { "name": "John Doe", "number": "1015" }, "caller": { "name": "Ronnie O'Sullivan", "number": "1000" }, "direction": "recipient", "state": "HUNGUP", "isClickToCall": false, "originatorId": "a40ad185-9e94-454b-a57a-b52ae6029ba6" } } Keepalive This message, sent every 30 seconds, indicates that the server connection is still active. Clients should use this application level keep alive as an indicator of a healthy connection as not all WebSocket client libraries support the direct use of the WebSocket ping / pong exchange. Note: There are no Keepalive messages sent by the Realtime API when using the Notification Channel. { "type":"keepalive" }