The contact center pushes live events over two WebSocket channels. The agent channel delivers status changes and call assigned / call ended events for one agent. The supervisor channel delivers every agent's status changes for the workspace. Connect with a signed-in user's access token in the token query parameter; API keys are not accepted on WebSockets.
Channels#
| Channel | URL | Receives |
|---|---|---|
| Agent | wss://voice-api.edesy.in/v1/ccaas/ws/agent?token=ACCESS_TOKEN&agent_id=AGENT_ID |
agent.status.change, agent.call.assigned, agent.call.ended for that agent |
| Supervisor | wss://voice-api.edesy.in/v1/ccaas/ws/supervisor?token=ACCESS_TOKEN |
agent.status.change for every agent in the workspace |
Message format#
Every message is JSON:
{
"type": "agent.status.change",
"timestamp": 1761643512000,
"data": { }
}
timestamp is in milliseconds since the Unix epoch.
Events#
agent.status.change#
Sent to supervisors and to the agent when an agent's status changes.
{
"agent_id": "8e1f...",
"agent_number": "1001",
"status": "break",
"status_reason": "Lunch",
"changed_at": "2026-10-28T08:05:12Z"
}
status is one of available, on_call, busy, break, wrap_up, offline. While a call rings an agent, status is busy with status_reason ringing.
agent.call.assigned#
Sent to the agent when a queue call is connected to them.
{ "queue_call_id": "b2c4...", "queue": "...", "caller": "+919876543210", "status": "connected" }
agent.call.ended#
Sent to the agent when the call ends.
{ "queue_call_id": "b2c4...", "status": "completed", "wrap_up": true }
wrap_up is true when the agent moved to wrap-up and should submit a disposition.
Keep-alive#
Send {"type": "ping"} at any time. The server answers {"type": "pong", "timestamp": ...}.
How to connect#
- Sign the user in with Edesy single sign-on and get their access token.
- Open the socket with
token(andagent_idfor the agent channel). - Send a ping every 30 seconds or so to keep proxies from closing an idle connection.
- Reconnect with backoff if the socket closes, and re-read
/ccaas/metrics/realtimeto catch up.
FAQ#
Why does my API key get a 401 on the WebSocket?#
WebSockets validate user access tokens only. Use the token of a signed-in user.
Can I send the token in a header?#
Authorization: Bearer ... is also read, but browsers cannot set headers on WebSockets, so the query parameter is the usual way.
Are queue and call metrics pushed?#
No. Totals such as calls waiting are not pushed today; poll GET/v1/ccaas/metrics/realtime.
Do events replay after a reconnect?#
No. Events are live only. Re-read state from the REST API after reconnecting.
Is delivery guaranteed?#
No. Events are best-effort. Use webhooks for outcomes your systems must not miss.
Can I connect several tabs for one agent?#
Keep one agent desktop tab per agent so events and calls go to one place.