---
title: "Connect a WebSocket as a leg (HTTP upgrade)"
method: GET
path: "/legs/websocket"
tags: ["Legs"]
---

# Connect a WebSocket as a leg (HTTP upgrade)

`GET /legs/websocket`

Upgrades the HTTP request to a WebSocket and creates a `websocket_in` leg. Query parameters: `sample_rate` (8000/16000/24000/48000; default 16000); `wire_format` (`binary` default, or `json_base64`); `sample_format` (`s16le` only in v1); `room_id` to auto-add the leg to a room; `app_id` for event filtering; `rtt=true` to enable the bidirectional text channel; `webhook_url`/`webhook_secret` for per-leg event routing. X-* and P-* request headers (plus Authorization) are captured into the leg's `headers` map and surfaced on `leg.ringing` and in `LegView`. The leg goes straight to `connected` (no ringing/answer flow). Audio frames carry PCM16-LE mono at `sample_rate`; with `wire_format=binary` each WebSocket binary frame is exactly one 20ms PCM frame, with `json_base64` the same payload is wrapped as `{"type":"audio","audio":"<base64>"}`. Text and control messages always use JSON text frames: `{"type":"text","text":...}`, `{"type":"ping","event_id":N}`/`{"type":"pong","event_id":N}`, and `{"type":"hangup"}` to terminate from the peer side.

## Other responses

- `101` — Switching Protocols — WebSocket upgrade succeeded
- `400` — Invalid query parameters
- `500` — Room create failure

---

[API](https://skmtc.net/voiceblender/apis/voiceblender-api.md) · [All operations](https://skmtc.net/voiceblender/apis/voiceblender-api/llms.txt) · [OpenAPI document](https://skmtc-service-staging.skmtc.workers.dev/v1/apis/voiceblender/voiceblender-api/versions/ad30827d3b57/schema)
