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

EnvironmentURL
Sandboxwss://engagement-api-sandbox.pypestream.com/socket/websocket
Livewss://engagement-api.pypestream.com/socket/websocket

Connection Variables

A sample WebSocket connection requires the following variables are included in the request:

VariableDescription
tokenThe 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:

EventSourceDescription
chat:startClientStarts 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:readyPypestreamInforms 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:pingClientResets 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:pongPypestreamThis is sent from Pypestream back to the client as a response to the ping message.
msg:sendClientA message transmitted from the End User to the MicroApp.
incoming:msgPypestreamA message transmitted from the MicroApp to the End User.
chat:endClientTerminates the chat established between the End User and the MicroApp.
chat:snapshotClientA request for a Snapshot of the Engagement.
chat:snapshot_responsePypestreamAn 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:

VariableTypeRequired (Y/N)Description
app_idstringYThe ID of the interface this engagement is associated to.
consumerstringYThe ID of the consumer interacting in this engagement.
gatewaystringYGateway type. Possible values are:

- pypestream_widget
pype_idstringYThe ID of the Pype tenant.
stream_idstringYThe ID of the Stream.
user_idstringYThe ID of the user interacting in this engagement.
versionstringYInternal message version. Valid values:
- 1
access_tokenstringYThe access token received in the User Creation Response

chat:ready

The chat:ready message payload has the following fields:

VariableTypeRequired (Y/N)Description
chat_IDstringYThe Engagement ID.

new:ping

The new:ping message payload has the following fields:

VariableTypeRequired (Y/N)Description
seqnumberYThe sequential identifer.
user_idstringYUser ID of the user submitting the message.
access_tokenstringYThe access token received on the User Creation Response

new:pong

The new:pong message payload has the following fields:

VariableTypeRequired (Y/N)Description
seqnumberYThe sequential identifer.
user_idstringYUser ID of the user submitting the message.

msg:send

The msg:send message payload has the following variables:

VariableTypeRequired (Y/N)Description
app_objectstringNAn object for the embedded object data. Passes through on platform side.
campaign_idstringNThe id of the campaign this message originated from.
client_msg_idstringNClient generated unique message id.
correlation_idstringNA unique ID set by the client which can be used to correlate the responding acknowledgement of the request.
filestringNA URL to a file to embed in the message.
file_statusstringNIndicates if the file is available for downloading from the URL. States are:

uploading
ready
failed
fromstringYUserID of the user submitting the message.
from_sidestringYIndicates the source of the message:

consumer
anonymous_consumer
gatewaystringYGateway type. Possible values are:

- pypestream_widget
-live_agent_consumer_widget
- live_agent_business
- pypestream_bot
msgstringNThe contents of the message being submitted.
msg_typestringYThe type of message. Possible values are:

text
embed
persist_to_historybooleanNFlags whether this message should be written to the persistent history.
requeuedintegerNSystem use only.
secure_app_objectbooleanNFlags whether this is a secure message and thus should not be persisted.
user_idstringYUserID of the user submitting the message.
versionintegerYInternal message version. Possible values are:

1
access_tokenstringYThe access token received on the User Creation Response

incoming:msg

The incoming:msg message payload has the following variables:

VariableTypeRequired (Y/N)Description
chat_idstringYID of the conversation you're receiving message from.
msg_actionstringNAction of the message:
- new
- update
fromstringYUserID of the user submitting the message.
from_sidestringYIndicates the source of the message:

- company
- agent
- manager
- bot
- system
- anonymous_consumer
msg_typestringYThe type of message. Possible values are:

- text
- embed
seq_numintegerNSequence from messages from internal server
timestampintegerNDatetime in Unixtime format
msgstringYThe contents of the message being submitted.
client_msg_idstringNClient generated unique message id.
filestringNA URL to a file to embed in the message.
file_statusstringNIndicates if the file is available for downloading from the URL. States are:

- uploading
- ready
- failed
app_objectstringNAn object for the embedded object data.
orig_app_objectstringNThe original embedded object data if it has been changed
secure_app_objectbooleanNFlags whether this is a secure message and thus should not be persisted.
free_textbooleanNFlags whether this is free text message.
campaign_idstringNThe id of the campaign this message originated from.
metadataarray[object]NMetadata of the message
encryptedbooleanNFlags whether this message is encrypted.
persist_to_historybooleanNFlags whether this message should be written to the persistent history.
eventsarray[object]NList of events

chat:end

The chat:end message payload has the following variables:

VariableTypeRequired (Y/N)Description
end_commentstringComment added by the agent when ending a conversation.
end_tagsArray[string]List of tags added by the agent when ending a conversation.
ended_bystringThe agent which ended the chat.
extra_dataintegerA list of key values.
pype_idstringPype id to which this chat belongs.
requeuedintegerSystem use only.
sourcestringThe source the chat conversation was ended by. Possible values are:

agent
consumer
user_idstringUser ID of the user submitting the message.
versionintegerInternal message version. Possible values are:
1
access_tokenstringThe access token received on the Create User Response

chat:snapshot

The chat:snapshot message payload has the following variables:

VariableTypeRequiredDescription
fromstringYUserID of whom requested the snapshot.
access_tokenstringYThe access token received on the Create User Response

chat:snapshot_response

The chat:snapshot_response message payload has the following variables:

VariableTypeRequired (Y/N)Description
idstringYThe ID of the engagement
botstringNThe microapp ID
bot_namestringNName of the MicroApp used.
bot_enabledbooleanNFlag if the engagement has a MicroApp enabled.
bot_msg_countintegerNThe number of messages sent by the microapp
bot_started_countintegerNThe number of MicroApps used.
with_end_botbooleanNIndicates if the engagement contains a survey microapp
target_bot_nodestringNLast node of the MicroApp reached.
app_idstringNThe ID of the Pype to engage with
pype_idstringNPype ID
pype_namestringNID of the Pype
stream_idstringNID of the Stream
stream_namestringNName of the Stream
consumerstringNThe ID of the consumer
consumer_namestringNThe Name of the consumer
consumer_typestringNType of consumer. Possible values:

anonymous
server
consumer_msg_countstringNThe number of messages sent by the consumer
originator_user_idstringNThe ID of the user who originated the engagement
originator_namestringNThe name of the user who originated the engagement
originating_sidestringNWhich side started the chat. Possible values:

consumer
bot
agent
agentstringNID of Agent assigned to the engagement.
agent_namestringNThe name of the agent assigned to the engagement.
agent_routingstringNWho routed this agent.
agent_is_assignedbooleanNIndicates if an agent is assigned to the engagement
agent_msg_countintegerNThe number of messages sent by the agent
agent_assign_tsintegerNUnixtime of the agent assignment time
agent_response_tsintegerNUnixtime of the last agent response
participant_changedbooleanNIndicates if the engagement participant has changed
participantsarray[object]NList of participants of the engagement
participant_historyarray[object]NList of participants changes of the engagement
start_tsintegerNUnixtime for start of the engagement
end_tsintegerNUnixtime for end of the engagement
last_updatedstringN
ended_bystringNThe ID of the user that ended the engagement
end_tagsstringNEngagement end tags
end_commentstringNEngagement end comment
gatewaystringNPlatform used by the client app (pypestream_widget, live_agent_consumer_widget, live_agent_business, pypestream_bot)
historyarray[object]NList of all messages of the engagement
delivery_receiptsarray[object]NList of delivery receipts from consumer received in the chat.
gateway_metadataobjectNMetadata of the engagement
user_read_countsarray[object]NList of consumer reads.
read_receiptsarray[object]NList of read receipts from consumer received in the engagement.
versionstringNchat:snapshot_response version
seq_numintegerNSequential number of the last message received or sent
statusstringNStatus of the engagement
access_tokenstringNThe 'access_token' received on the Create User response.
encryptedbooleanNIndicates if the engagement is encrypted
persist_bot_historybooleanNIndicates if the engagement should save the microapp history
initial_msgstringNInitial 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 CodeReasonDescription
HTTP 400Missing ParameterA requested parameter is missing from the connection request (either token or user_id).
HTTP 403Invalid TokenThe authentication token is invalid. Please see Create User for more details.
WebSocket 1007Invalid MessageThe message is in the improper format.
WebSocket 1000TimeoutThe WebSocket session has timed out.