Overview
The Engagement API uses WebSockets to open a two-way interactive communication session between the user's browser and a server. With a WebSocket, you can send messages to a server and receive event-driven responses without having to poll the server for a reply.
Steps
After creating a user, you will need to establish a WebSocket connection.
Once the WebSocket connection is established, join the chat channel chat:{CHAT_ID} by using the join function of the Elixir/Channels library (see an example Phoenix Channels JavaScript client) in order to receive messages from Pypestream and to send and receive the heartbeat protocol messages to keep the connection established. Join the chat channel before you start the engagement, otherwise, you will not receive the initial messages from the microapp you are interacting with.
After you send the request to start the engagement, you need to wait until you receive the chat:ready
event through the Websocket. This will indicate that you can proceed and use the other endpoints such as sending a message. If a request is sent before receiving the chat:ready
event, the API will return an error 428.
When receiving a response, the event incoming:msg
will received in the WebSocket.
URLs
Environment | URL |
---|---|
Sandbox | wss://engagement-api-sandbox.pypestream.com/socket/websocket |
Live | wss://engagement-api.pypestream.com/socket/websocket |
Connection Variables
A sample WebSocket connection requires the following variables are included in the request:
Variable | Description |
---|---|
token | The access token. This is generated through the Create User request. |
For example, a Websocket connection using the Phoenix Channels JavaScript client would look like this, where MY_TOKEN is the token retrieved through the Create User:
let socket = new Socket("wss://{URL}/socket/websocket", {params: {token: {MY_TOKEN}}})
socket.connect()
Joining a Channel
In order to join a channel, use the join function including the topic you're connecting to and the authorization information for that channel. Once connected to the WebSocket using the Phoenix Channels JavaScript client and establishing a connection on the channel variable, this step would look like this:
let channel = socket.channel("chat:{ChatID}", {user_id: "{UserID}", access_token: "{AccessToken}"})
channel.join()
.receive("ok", ({messages}) => {YourSuccessFunction} )
.receive("error", ({reason}) => {YourFailureFunction} )
.receive("timeout", () => {YourTimeoutFunction})
Replace the {ChatID}, {UserID} and {AccessToken} with their respective value.
What is a topic?
A topic is the representation of the chat. The topic will always be a string in the following form "chat:{ChatID}", for example "chat:42c6a240-1bf9-4164-8d75-9a608f1117c9". Before sending or receiving any messages, we join the "topic" by using the join function from the library you're using.
Events
The following messages can be sent through the WebSocket connection:
Event | Source | Description |
---|---|---|
chat:start | Client | Starts the engagement. After sending this event, the client must wait for the chat:ready event that will indicate that everything is ready to receive messages |
chat:ready | Pypestream | Informs the Client that the chat is ready to receive send_message requests, if a message is received before getting this event it will be rejected with a 428 status |
new:ping | Client | Resets the connection counter timeout. This is used to keep the connection from disconnecting from the timeout setting. A ping message should be sent every 20 seconds to prevent disconnection. |
new:pong | Pypestream | This is sent from Pypestream back to the client as a response to the ping message. |
msg:send | Client | A message transmitted from the End User to the MicroApp. |
incoming:msg | Pypestream | A message transmitted from the MicroApp to the End User. |
chat:end | Client | Terminates the chat established between the End User and the MicroApp. |
chat:snapshot | Client | A request for a Snapshot of the Engagement. |
chat:snapshot_response | Pypestream | An object with all the relevant information of the engagement at the moment the request was done. |
chat:start
The chat:start message payload has the following fields:
Variable | Type | Required (Y/N) | Description |
---|---|---|---|
app_id | string | Y | The ID of the interface this engagement is associated to. |
consumer | string | Y | The ID of the consumer interacting in this engagement. |
gateway | string | Y | Gateway type. Possible values are: - pypestream_widget |
pype_id | string | Y | The ID of the Pype tenant. |
stream_id | string | Y | The ID of the Stream. |
user_id | string | Y | The ID of the user interacting in this engagement. |
version | string | Y | Internal message version. Valid values: - 1 |
access_token | string | Y | The access token received in the User Creation Response |
chat:ready
The chat:ready message payload has the following fields:
Variable | Type | Required (Y/N) | Description |
---|---|---|---|
chat_ID | string | Y | The Engagement ID. |
new:ping
The new:ping message payload has the following fields:
Variable | Type | Required (Y/N) | Description |
---|---|---|---|
seq | number | Y | The sequential identifer. |
user_id | string | Y | User ID of the user submitting the message. |
access_token | string | Y | The access token received on the User Creation Response |
new:pong
The new:pong message payload has the following fields:
Variable | Type | Required (Y/N) | Description |
---|---|---|---|
seq | number | Y | The sequential identifer. |
user_id | string | Y | User ID of the user submitting the message. |
msg:send
The msg:send message payload has the following variables:
Variable | Type | Required (Y/N) | Description |
---|---|---|---|
app_object | string | N | An object for the embedded object data. Passes through on platform side. |
campaign_id | string | N | The id of the campaign this message originated from. |
client_msg_id | string | N | Client generated unique message id. |
correlation_id | string | N | A unique ID set by the client which can be used to correlate the responding acknowledgement of the request. |
file | string | N | A URL to a file to embed in the message. |
file_status | string | N | Indicates if the file is available for downloading from the URL. States are: uploading ready failed |
from | string | Y | UserID of the user submitting the message. |
from_side | string | Y | Indicates the source of the message: consumer anonymous_consumer |
gateway | string | Y | Gateway type. Possible values are: - pypestream_widget -live_agent_consumer_widget - live_agent_business - pypestream_bot |
msg | string | N | The contents of the message being submitted. |
msg_type | string | Y | The type of message. Possible values are: text embed |
persist_to_history | boolean | N | Flags whether this message should be written to the persistent history. |
requeued | integer | N | System use only. |
secure_app_object | boolean | N | Flags whether this is a secure message and thus should not be persisted. |
user_id | string | Y | UserID of the user submitting the message. |
version | integer | Y | Internal message version. Possible values are: 1 |
access_token | string | Y | The access token received on the User Creation Response |
incoming:msg
The incoming:msg message payload has the following variables:
Variable | Type | Required (Y/N) | Description |
---|---|---|---|
chat_id | string | Y | ID of the conversation you're receiving message from. |
msg_action | string | N | Action of the message: - new - update |
from | string | Y | UserID of the user submitting the message. |
from_side | string | Y | Indicates the source of the message: - company - agent - manager - bot - system - anonymous_consumer |
msg_type | string | Y | The type of message. Possible values are: - text - embed |
seq_num | integer | N | Sequence from messages from internal server |
timestamp | integer | N | Datetime in Unixtime format |
msg | string | Y | The contents of the message being submitted. |
client_msg_id | string | N | Client generated unique message id. |
file | string | N | A URL to a file to embed in the message. |
file_status | string | N | Indicates if the file is available for downloading from the URL. States are: - uploading - ready - failed |
app_object | string | N | An object for the embedded object data. |
orig_app_object | string | N | The original embedded object data if it has been changed |
secure_app_object | boolean | N | Flags whether this is a secure message and thus should not be persisted. |
free_text | boolean | N | Flags whether this is free text message. |
campaign_id | string | N | The id of the campaign this message originated from. |
metadata | array[object] | N | Metadata of the message |
encrypted | boolean | N | Flags whether this message is encrypted. |
persist_to_history | boolean | N | Flags whether this message should be written to the persistent history. |
events | array[object] | N | List of events |
chat:end
The chat:end message payload has the following variables:
Variable | Type | Required (Y/N) | Description |
---|---|---|---|
end_comment | string | Comment added by the agent when ending a conversation. | |
end_tags | Array[string] | List of tags added by the agent when ending a conversation. | |
ended_by | string | The agent which ended the chat. | |
extra_data | integer | A list of key values. | |
pype_id | string | Pype id to which this chat belongs. | |
requeued | integer | System use only. | |
source | string | The source the chat conversation was ended by. Possible values are: agent consumer | |
user_id | string | User ID of the user submitting the message. | |
version | integer | Internal message version. Possible values are: 1 | |
access_token | string | The access token received on the Create User Response |
chat:snapshot
The chat:snapshot message payload has the following variables:
Variable | Type | Required | Description |
---|---|---|---|
from | string | Y | UserID of whom requested the snapshot. |
access_token | string | Y | The access token received on the Create User Response |
chat:snapshot_response
The chat:snapshot_response message payload has the following variables:
Variable | Type | Required (Y/N) | Description |
---|---|---|---|
id | string | Y | The ID of the engagement |
bot | string | N | The microapp ID |
bot_name | string | N | Name of the MicroApp used. |
bot_enabled | boolean | N | Flag if the engagement has a MicroApp enabled. |
bot_msg_count | integer | N | The number of messages sent by the microapp |
bot_started_count | integer | N | The number of MicroApps used. |
with_end_bot | boolean | N | Indicates if the engagement contains a survey microapp |
target_bot_node | string | N | Last node of the MicroApp reached. |
app_id | string | N | The ID of the Pype to engage with |
pype_id | string | N | Pype ID |
pype_name | string | N | ID of the Pype |
stream_id | string | N | ID of the Stream |
stream_name | string | N | Name of the Stream |
consumer | string | N | The ID of the consumer |
consumer_name | string | N | The Name of the consumer |
consumer_type | string | N | Type of consumer. Possible values: anonymous server |
consumer_msg_count | string | N | The number of messages sent by the consumer |
originator_user_id | string | N | The ID of the user who originated the engagement |
originator_name | string | N | The name of the user who originated the engagement |
originating_side | string | N | Which side started the chat. Possible values: consumer bot agent |
agent | string | N | ID of Agent assigned to the engagement. |
agent_name | string | N | The name of the agent assigned to the engagement. |
agent_routing | string | N | Who routed this agent. |
agent_is_assigned | boolean | N | Indicates if an agent is assigned to the engagement |
agent_msg_count | integer | N | The number of messages sent by the agent |
agent_assign_ts | integer | N | Unixtime of the agent assignment time |
agent_response_ts | integer | N | Unixtime of the last agent response |
participant_changed | boolean | N | Indicates if the engagement participant has changed |
participants | array[object] | N | List of participants of the engagement |
participant_history | array[object] | N | List of participants changes of the engagement |
start_ts | integer | N | Unixtime for start of the engagement |
end_ts | integer | N | Unixtime for end of the engagement |
last_updated | string | N | |
ended_by | string | N | The ID of the user that ended the engagement |
end_tags | string | N | Engagement end tags |
end_comment | string | N | Engagement end comment |
gateway | string | N | Platform used by the client app (pypestream_widget, live_agent_consumer_widget, live_agent_business, pypestream_bot) |
history | array[object] | N | List of all messages of the engagement |
delivery_receipts | array[object] | N | List of delivery receipts from consumer received in the chat. |
gateway_metadata | object | N | Metadata of the engagement |
user_read_counts | array[object] | N | List of consumer reads. |
read_receipts | array[object] | N | List of read receipts from consumer received in the engagement. |
version | string | N | chat:snapshot_response version |
seq_num | integer | N | Sequential number of the last message received or sent |
status | string | N | Status of the engagement |
access_token | string | N | The 'access_token' received on the Create User response. |
encrypted | boolean | N | Indicates if the engagement is encrypted |
persist_bot_history | boolean | N | Indicates if the engagement should save the microapp history |
initial_msg | string | N | Initial message of engagement |
Example
Here is an example to push events to the channel and listen to events. In the following example, the channel is set up to listen for the "new_msg" event and send the "new_msg" event back to the Websocket.
Please see the Phoenix Channels JavaScript client documentation
let channel = socket.channel("room:123", {token: roomToken})
channel.on("new_msg", msg => console.log("Got message", msg) )
$input.onEnter( e => {
channel.push("new_msg", {body: e.target.val}, 10000)
.receive("ok", (msg) => console.log("created message", msg) )
.receive("error", (reasons) => console.log("create failed", reasons) )
.receive("timeout", () => console.log("Networking issue...") )
})
channel.join()
.receive("ok", ({messages}) => console.log("catching up", messages) )
.receive("error", ({reason}) => console.log("failed join", reason) )
.receive("timeout", () => console.log("Networking issue. Still waiting..."))
Status Codes
The following are the possible response codes based on the requests:
Status Code | Reason | Description |
---|---|---|
HTTP 400 | Missing Parameter | A requested parameter is missing from the connection request (either token or user_id). |
HTTP 403 | Invalid Token | The authentication token is invalid. Please see Create User for more details. |
WebSocket 1007 | Invalid Message | The message is in the improper format. |
WebSocket 1000 | Timeout | The WebSocket session has timed out. |