> ## Documentation Index
> Fetch the complete documentation index at: https://docs.sayna.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# LiveKit room management

> Manage LiveKit rooms and participants through Sayna's authenticated REST endpoints.

Sayna exposes a thin LiveKit management layer so you can list rooms, inspect participants, and moderate sessions without calling the LiveKit admin API directly. This keeps LiveKit credentials server-side and applies the same auth rules you already use across Sayna.

<Note>
  When `AUTH_REQUIRED=true`, all endpoints below require a token via the `Authorization: Bearer <token>` header or the `api_key` query parameter. The header is recommended by default.
</Note>

## Why Sayna wraps LiveKit

* Prevents exposing LiveKit API keys or admin endpoints to client applications.
* Enforces Sayna authentication and authorization for every management call.
* Keeps multi-tenant isolation consistent across REST and WebSocket flows.

## Published audio tracks

When a WebSocket session is audio-enabled and joins a LiveKit room, the Sayna agent participant publishes synthesized speech on an audio track named `"tts-audio"`. If that session's `config` message also includes a [`loading_audio`](/guides/websocket#loading_audio-configuration) object, the agent publishes a **second** audio track named `"loading-audio"` carrying the loading-indicator sound.

| Track name        | Carries                                                                   |
| ----------------- | ------------------------------------------------------------------------- |
| `"tts-audio"`     | Synthesized speech (text-to-speech output).                               |
| `"loading-audio"` | The loading-indicator clip, looped while the calling application is busy. |

The two tracks are independent and can be audible at the same time. LiveKit client SDKs automatically play every subscribed audio track, so participants hear both without any extra client-side handling.

<Info>
  Because `"loading-audio"` is a real published track, it is included in room-composite egress recordings alongside `"tts-audio"`. This is correct behavior — the recording faithfully reflects what the human participant heard.
</Info>

## Room ownership and access control

Room access is controlled via the `metadata.auth_id` field stored in room metadata. When authentication is enabled:

* **Room creation**: When you request a token for a room that doesn't exist, Sayna creates it and sets `metadata.auth_id` to your tenant ID.
* **Room access**: All room-scoped operations verify that `room.metadata.auth_id` matches your authenticated `auth.id`.
* **Access denied**: Unauthorized access returns `404 Not Found` (masked for security) or `403 Forbidden` depending on the operation.

<Info>
  Room names are no longer modified or prefixed. You send and receive clean room names exactly as specified.
</Info>

### Backward compatibility

When `auth.id` is absent (unauthenticated mode), all rooms are accessible. This maintains compatibility with deployments that don't require authentication.

## Endpoint overview

| Endpoint                         | Use case                                                                                               |
| -------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `POST /livekit/token`            | Mint participant tokens and create rooms. [API reference](/api-reference/endpoint/livekit-token)       |
| `GET /livekit/rooms`             | List rooms for the current tenant. [API reference](/api-reference/endpoint/livekit-rooms)              |
| `GET /livekit/rooms/{room_name}` | Inspect room details and participants. [API reference](/api-reference/endpoint/livekit-room)           |
| `DELETE /livekit/participant`    | Remove a participant from a room. [API reference](/api-reference/endpoint/livekit-participant)         |
| `POST /livekit/participant/mute` | Mute or unmute a participant track. [API reference](/api-reference/endpoint/livekit-participant-mute)  |
| `POST /sip/call`                 | Initiate an outbound SIP call. [API reference](/api-reference/endpoint/sip-call)                       |
| `POST /sip/transfer`             | Transfer a SIP participant to a new destination. [API reference](/api-reference/endpoint/sip-transfer) |

## Typical flow

<Steps>
  <Step title="Create a room and get a token">
    Call `POST /livekit/token` with your room name. If the room doesn't exist, Sayna creates it and sets `metadata.auth_id` to your tenant ID before returning the token.
  </Step>

  <Step title="List rooms">
    Call `GET /livekit/rooms` to discover active rooms. Only rooms with matching `metadata.auth_id` are returned.
  </Step>

  <Step title="Inspect a room">
    Use `GET /livekit/rooms/{room_name}` to fetch participant identities and metadata.
  </Step>

  <Step title="Moderate participants">
    Disconnect a participant with `DELETE /livekit/participant` or mute a track with `POST /livekit/participant/mute`.
  </Step>

  <Step title="Handle SIP calls">
    Initiate outbound calls with `POST /sip/call` or transfer existing SIP participants with `POST /sip/transfer`.
  </Step>
</Steps>

## Error handling

Room-scoped operations return specific errors for access control:

| Status                      | Meaning                                                                   |
| --------------------------- | ------------------------------------------------------------------------- |
| `403 Forbidden`             | Room exists with a different tenant's `auth_id` (token endpoint only).    |
| `404 Not Found`             | Room not found or access denied (masked for security on other endpoints). |
| `500 Internal Server Error` | LiveKit not configured or operation failed.                               |

<Tip>
  When you receive a `403` on token generation, the room already exists and is owned by another tenant. Choose a different room name or contact the room owner.
</Tip>

<Warning>
  Removing a participant does not revoke their LiveKit token. If you need to prevent rejoin, issue short-lived tokens and avoid re-minting them after removal.
</Warning>
