#Recipe: Live events (SSE / WebSocket)
For live dashboards: GET /v1/events/stream (Server-Sent Events) or GET /v1/events/ws (WebSocket),
both authenticated with the API key and filterable with types=call.*,agent.registered. Each message is
the same envelope as a webhook. Use it from your backend; browsers should get events through your
backend (never give the API key to a browser).
#TypeScript (SDK)
export {};
// Live call state for dashboards: Server-Sent Events (or WebSocket at /v1/events/ws).
const res = await fetch(`${process.env.VOICE_API_URL}/v1/events/stream?types=call.*,agent.registered`, {
headers: { authorization: `Bearer ${process.env.VOICE_API_KEY}` },
signal: AbortSignal.timeout(3000),
}).catch(() => null);
if (!res || !res.ok) throw new Error('stream not available');
const reader = res.body!.getReader();
const { value } = await reader.read();
console.log(new TextDecoder().decode(value)); // ": connected", then "event: call.answered\ndata: {...}"
await reader.cancel();
#Notes
- Missed events can be fetched with
GET /v1/events(filter bytypeorcall_id).
This example is executed against the sandbox in CI (tests/e2e/specs/m6-docs.spec.ts).