WebSocket connections¶
A WebSocket keeps a persistent, two-way channel open between client and server. ChannelX uses it to push platform events as they happen, so a dashboard or mobile client can update live without reloading. To connect, you authenticate with a token and subscribe to the channel.
Experimental
This feature is experimental and the details may change between releases. Backward compatibility isn't guaranteed, so always build against the latest version.
Why use a WebSocket¶
A WebSocket delivers real-time updates, which makes it ideal for clients such as an Android or iOS SDK. The dashboard reflects new messages and status changes instantly, improving the agent experience and productivity.
Connecting¶
Open a connection to wss://<your-installation-url>/cable using an authentication PubSub token from ChannelX. A PubSub token authenticates a client to the publish-subscribe service so it can subscribe to events.
There are two token types:
- User PubSub token — carries agent/admin privileges and receives every event listed below. Retrieve it from the Profile API.
- Contact PubSub token — generated per contact session. It only grants events for that session, such as
conversation.created,conversation.status_changed,message.created,message.updated,conversation.typing_on,conversation.typing_off, andpresence.update. When a contact is created through the public APIs, itspubsub_tokenis returned in the response.
Tokens can rotate
Depending on your installation, tokens may be rotated regularly. Always connect with the current token, and treat any PubSub token as a secret — it grants real-time access to conversation data.
To subscribe, send a subscribe command with your pubSubToken, accountId, and (for a user token) userId:
const stringify = (payload = {}) => JSON.stringify(payload);
const pubSubToken = "<contact/user-pub-sub-token>";
const accountId = "<your-account-id-in-integer>";
const userId = "<user-id-in-integer-if-using-user-token>";
const connection = new WebSocket("wss://<your-installation-url>/cable");
connection.send(
stringify({
command: "subscribe",
identifier: stringify({
channel: "RoomChannel",
pubsub_token: pubSubToken,
account_id: accountId,
user_id: userId,
}),
})
);
Publishing presence¶
To keep a user shown as online, send a presence update roughly every 30 seconds. For an agent or admin:
const userPayload = stringify({
command: "message",
identifier: stringify({
channel: "RoomChannel",
pubsub_token: "<user-pubsub-token>",
account_id: accountId,
user_id: userId,
}),
data: stringify({ action: "update_presence" }),
});
connection.send(userPayload);
For a contact, send the same update_presence action with just the channel and contact PubSub token in the identifier.
Payload objects¶
Events carry one of a few object types:
- Conversation — id, inbox, status, channel, the
contact_inboxlink, messages, and ametablock with sender and assignee. - Contact — id, name, email, phone number, identifier, thumbnail, and attribute objects.
- User — id, name, available name, avatar, and availability status.
- Message — id, content, type, content attributes, sender, and timestamps.
- Notification — id, type, the primary actor, read state, and timestamps.
Each event includes an identifier (channel, token, account, user) and a message carrying the event name and its data.
Event types¶
| Event | Sent to | Triggered when |
|---|---|---|
conversation.created |
agent/admin, contact | A new conversation starts. |
conversation.read |
agent/admin | A contact reads a message. |
message.created |
agent/admin, contact | A new message is created. |
message.updated |
agent/admin, contact | A message is updated. |
conversation.status_changed |
agent/admin, contact | A conversation's status changes. |
conversation.typing_on |
agent/admin, contact | A contact or agent starts typing (is_private marks a note). |
conversation.typing_off |
agent/admin, contact | Typing stops. |
assignee.changed |
agent/admin | The assigned agent changes. |
team.changed |
agent/admin | The assigned team changes. |
conversation.contact_changed |
agent/admin | Two contacts merge and their conversations consolidate. |
contact.created |
agent/admin | A contact is created. |
contact.updated |
agent/admin | A contact is updated. |
presence.update |
agent/admin, contact | Availability status changes. Contacts don't see other contacts' status. |
notification_created |
agent/admin | A notification is created. |
Each event payload follows the shape:
{
"message": {
"event": "message.created",
"data": { /* the relevant object */ }
}
}