Real-Time Events Guide
Connect to real-time events using WebSockets for instant updates.
Overview
Semaswift uses Centrifugo for real-time communication. Connect once and subscribe to channels for live updates on calls, agents, tickets, and more.
Connection Setup
Get Connection Token
POST /api/v1/realtime/token
Authorization: Bearer YOUR_TOKEN
{
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"expires_at": "2024-01-15T11:30:00Z"
}
Connect to WebSocket
import { Centrifuge } from 'centrifuge';
const centrifuge = new Centrifuge('wss://realtime.semaswift.com/connection/websocket', {
token: connectionToken
});
centrifuge.on('connected', (ctx) => {
console.log('Connected:', ctx);
});
centrifuge.on('disconnected', (ctx) => {
console.log('Disconnected:', ctx);
});
centrifuge.connect();
Available Channels
Voice Channels
| Channel | Events |
|---|---|
voice:calls | All call events |
voice:agents | Agent status changes |
voice:queue:{id} | Specific queue events |
Ticketing Channels
| Channel | Events |
|---|---|
tickets:all | All ticket updates |
tickets:mine | Assigned ticket updates |
tickets:{id} | Specific ticket |
User Channels
| Channel | Events |
|---|---|
user:{id} | Personal notifications |
presence:online | Online/offline status |
Subscribing to Channels
// Subscribe to call events
const callsSub = centrifuge.newSubscription('voice:calls');
callsSub.on('publication', (ctx) => {
const event = ctx.data;
switch (event.type) {
case 'call.started':
console.log('New call:', event.data);
break;
case 'call.ended':
console.log('Call ended:', event.data);
break;
}
});
callsSub.subscribe();
Event Types
Call Events
{
"type": "call.started",
"data": {
"call_id": "call_123",
"direction": "inbound",
"from": "+1-555-123-4567",
"to": "+1-555-987-6543",
"queue_id": "queue_support",
"started_at": "2024-01-15T10:30:00Z"
}
}
Agent Events
{
"type": "agent.status_changed",
"data": {
"agent_id": "agent_123",
"previous_status": "available",
"new_status": "on_call",
"timestamp": "2024-01-15T10:30:00Z"
}
}
Ticket Events
{
"type": "ticket.updated",
"data": {
"ticket_id": "tkt_123",
"changes": {
"status": {"from": "open", "to": "pending"},
"assignee_id": {"from": null, "to": "usr_456"}
},
"updated_by": "usr_789",
"updated_at": "2024-01-15T10:30:00Z"
}
}
Presence
Track who's online:
const presenceSub = centrifuge.newSubscription('presence:online');
presenceSub.on('join', (ctx) => {
console.log('User joined:', ctx.info);
});
presenceSub.on('leave', (ctx) => {
console.log('User left:', ctx.info);
});
// Get current presence
presenceSub.presence().then((result) => {
console.log('Online users:', result.clients);
});
Error Handling
centrifuge.on('error', (ctx) => {
console.error('Connection error:', ctx);
if (ctx.code === 109) {
// Token expired - refresh and reconnect
refreshToken().then((newToken) => {
centrifuge.setToken(newToken);
});
}
});
callsSub.on('error', (ctx) => {
console.error('Subscription error:', ctx);
});
Best Practices
- Handle reconnection - Auto-reconnect is built-in
- Refresh tokens - Before expiry
- Unsubscribe - When leaving a page
- Batch updates - Don't update UI on every event
- Use presence sparingly - It has higher overhead