---
title: "Add or move a leg to a room"
method: POST
path: "/rooms/{id}/legs"
tags: ["Rooms"]
---

# Add or move a leg to a room

`POST /rooms/{id}/legs`

Add a leg to a room (auto-creates room if it doesn't exist). If the leg is already in a different room, it is atomically moved to the target room. A ringing inbound SIP leg is automatically answered before being added — in this case the response status is `adding` and the actual room join happens asynchronously, observable via `leg.joined_room`. Auto-answer failures surface as `leg.command_failed` with `command="add_to_room"`. Only the leg's primary audio stream joins by default; `streams` additionally mixes named secondary streams of the same leg into this room. A stream currently mixed elsewhere is moved here.

## Request body

- AddLegRequest
  - `leg_id` string, required — ID of the leg to add
  - `mute` boolean — If set, apply this mute state to the leg atomically before it joins the mixer (no race where un-muted audio enters the mix). Omit to leave current state untouched (useful when moving between rooms).
  - `deaf` boolean — If set, apply this deaf state to the leg atomically before it joins the mixer. Omit to leave current state untouched.
  - `accept_dtmf` boolean — If set, control whether this leg receives DTMF digits broadcast from other legs in the same room. Omit to leave current state untouched (default for new legs is true).
  - `role` string — If set, apply this routing role to the leg atomically before it joins the mixer. The room's routing matrix (see PUT /v1/rooms/{id}/routing) decides which other legs this leg hears and is heard by based on roles. Pass "" to clear the role (full mesh). Omit to leave the current role untouched.
  - `streams` AddRoomStream[] — Additional audio streams of the leg to mix into this room, each with its own routing role. Omit to add only the leg's primary stream. A stream already mixed elsewhere is moved here.
    - `stream_id` string, required — Stream identifier from GET /v1/legs/{id}/streams. The primary stream is not addressable here — it joins with the leg itself.
    - `role` string — Routing role for this stream inside the room.

## Response `200`

Leg added or moved

- StatusResponse
  - `instance_id` string — Instance identifier
  - `status` string, required

## Other responses

- `400` — Invalid JSON, leg not found, or leg not connected

---

[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/revisions/c951ca5dcd08/schema)
