Server → Client Events
Events the server pushes to connected clients for real-time updates on messages, conversations, typing, and presence.
Overview
These events are broadcast by the server to connected clients. Register handlers before starting the connection to ensure you don't miss events during the startup window.
// Always register handlers BEFORE calling connection.start()
connection.on("MessageReceived", (payload) => { /* ... */ });
connection.on("ConversationCreated", (payload) => { /* ... */ });
connection.on("ConversationUpdated", (payload) => { /* ... */ });
connection.on("TypingChanged", (payload) => { /* ... */ });
connection.on("PresenceChanged", (payload) => { /* ... */ });
await connection.start();MessageReceived
Fired when a new message is sent in a conversation. Delivered to all members of the conversation:{id} group and the tenant:{id} group.
{
"id": "msg_abc123",
"conversationId": "conv_def456",
"content": "Hi, I need help with my order",
"senderType": "visitor",
"senderName": "John Doe",
"senderId": null,
"isInternal": false,
"createdAt": "2024-01-15T14:30:00Z"
}senderType—"visitor"or"agent"senderId— Agent ID if sender is an agent, null for visitorsisInternal— Alwaysfalsefor messages sent to visitors. Internal notes are only broadcast to the tenant group.
isInternal: true) are only sent to the tenant:{tenantId} group. Visitors never receive events where isInternal is true.ConversationCreated
Fired when a visitor starts a new conversation. Delivered to the tenant:{id} group so all online agents see it in their inbox.
{
"id": "conv_new789",
"visitorName": "Alice Customer",
"visitorEmail": "[email protected]",
"status": "open",
"lastMessage": {
"content": "I have a question about pricing",
"senderType": "visitor",
"createdAt": "2024-01-15T14:30:00Z"
},
"createdAt": "2024-01-15T14:30:00Z"
}ConversationUpdated
Fired when a conversation's metadata changes (status change, agent assigned, etc.). Delivered to both the tenant:{id} and conversation:{id} groups.
{
"id": "conv_abc123",
"status": "assigned",
"assignedAgentId": "agt_xyz789",
"assignedAgent": {
"id": "agt_xyz789",
"fullName": "Sarah Agent"
},
"updatedAt": "2024-01-15T14:35:00Z",
"closedAt": null
}The payload includes only the fields that changed, plus the id for lookup. Clients should merge this into their local state.
TypingChanged
Fired when someone starts or stops typing in a conversation. Delivered to the conversation:{id} group.
{
"conversationId": "conv_abc123",
"userId": "agt_xyz789",
"userName": "Sarah Agent",
"userType": "agent",
"isTyping": true
}userType—"visitor"or"agent"isTyping—truewhen typing starts,falsewhen stopped
Clients should auto-clear typing indicators after 5 seconds of no update (as a safety net if the isTyping: false event is missed due to disconnection).
PresenceChanged
Fired when an agent comes online or goes offline. Delivered to the tenant:{id} group.
{
"agentId": "agt_xyz789",
"fullName": "Sarah Agent",
"status": "online",
"lastSeenAt": "2024-01-15T14:30:00Z"
}status—"online"or"offline"lastSeenAt— Timestamp of last activity, updated on disconnect
PresenceChanged event fires.Event Delivery Guarantees
- Events are delivered at-most-once — if the client is disconnected, missed events are not replayed
- After reconnection, clients should fetch the latest state via REST API to catch up
- Events are ordered within a single connection but ordering is not guaranteed across reconnections
- Typing and presence events are ephemeral — they're never persisted or retried