# WebSocket Events

> Real-time contact-center events over WebSocket - agent and supervisor channels, authentication, message format and event payloads.

Source: https://edesy.in/docs/contact-center/api/websocket-events

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:

```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.

```json
{
  "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.

```json
{ "queue_call_id": "b2c4...", "queue": "...", "caller": "+919876543210", "status": "connected" }
```

### agent.call.ended

Sent to the agent when the call ends.

```json
{ "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

1. **Sign the user in** with Edesy single sign-on and get their access token.
2. **Open the socket** with `token` (and `agent_id` for the agent channel).
3. **Send a ping** every 30 seconds or so to keep proxies from closing an idle connection.
4. **Reconnect** with backoff if the socket closes, and re-read `/ccaas/metrics/realtime` to 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](https://edesy.in/docs/contact-center/api/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.
