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

# Voice agents CRUD

> Create and manage voice agent routing aliases for AI-powered call handling.

A voice agent is a tenant-scoped routing alias that tells Yotel where to
send audio when a call is answered. It maps a name to a WebSocket URL,
authentication config, audio format, and concurrency limits.

<Info>
  Voice agents define **routing**, not behavior. Your AI service receives
  the audio stream and decides what to do. See the
  [Voice agents quickstart](/voice-agents/quickstart) for the integration flow.
</Info>

## Create a voice agent

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.yotel.in/api/v1/voice-agents \
    -H "Authorization: Bearer yt_live_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "name": "Support bot v2",
      "ws_url": "wss://ai.example.com/ws",
      "auth_token": "secret_token_123",
      "max_concurrent": 50,
      "audio_format": {
        "encoding": "pcm_s16le",
        "sample_rate_hz": 16000,
        "channels": 1,
        "frame_ms": 20
      }
    }'
  ```

  ```python Python theme={null}
  va = client.voice_agents.create(
      name="Support bot v2",
      ws_url="wss://ai.example.com/ws",
      auth_token="secret_token_123",
      max_concurrent=50,
  )
  print(va.id)
  ```

  ```typescript TypeScript theme={null}
  const va = await client.voiceAgents.create({
    name: "Support bot v2",
    ws_url: "wss://ai.example.com/ws",
    auth_token: "secret_token_123",
    max_concurrent: 50,
  });
  console.log(va.id);
  ```
</CodeGroup>

**Scope:** `voice_agents:write`  |  **Status:** `201 Created`

### Request body

| Field                  | Type           | Default                | Description                                                                            |
| ---------------------- | -------------- | ---------------------- | -------------------------------------------------------------------------------------- |
| `name`                 | string         | —                      | Display name (1–200 chars, required)                                                   |
| `ws_url`               | string         | —                      | WebSocket endpoint for audio streaming (must start with `ws://` or `wss://`, required) |
| `auth_token`           | string \| null | `null`                 | Static token sent in the WebSocket handshake                                           |
| `audio_format`         | object         | See below              | Audio encoding config                                                                  |
| `external_agent_id`    | string \| null | `null`                 | Your internal ID for cross-referencing                                                 |
| `transfer_destination` | string \| null | `null`                 | Default transfer target (E.164 or SIP URI)                                             |
| `max_concurrent`       | integer        | `10`                   | Max simultaneous sessions (1–10,000). Redis-enforced; exceeding returns `429`.         |
| `token_lifetime`       | string         | `"30min_with_refresh"` | `"30min_with_refresh"` or `"ws_session"`                                               |
| `subprotocol`          | string         | `"audio.drachtio.org"` | `"audio.drachtio.org"` or `"audio.jambonz.org"`                                        |
| `ws_disconnect_action` | string         | `"hangup"`             | What happens when your WS disconnects: `"hangup"` or `"transfer_to_queue"`             |

### Default audio format

```json theme={null}
{
  "encoding": "pcm_s16le",
  "sample_rate_hz": 16000,
  "channels": 1,
  "frame_ms": 20
}
```

***

## List voice agents

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.yotel.in/api/v1/voice-agents \
    -H "Authorization: Bearer yt_live_YOUR_KEY"
  ```

  ```python Python theme={null}
  agents = client.voice_agents.list()
  ```

  ```typescript TypeScript theme={null}
  const agents = await client.voiceAgents.list();
  ```
</CodeGroup>

**Scope:** `voice_agents:read`  |  **Status:** `200 OK`

Optional query parameter: `status` — filter by `"active"`, `"paused"`, or `"archived"`.

### Response

```json theme={null}
{
  "items": [ /* VoiceAgentResponse objects */ ],
  "total": 3
}
```

***

## Get a voice agent

<CodeGroup>
  ```bash curl theme={null}
  curl https://api.yotel.in/api/v1/voice-agents/{voice_agent_id} \
    -H "Authorization: Bearer yt_live_YOUR_KEY"
  ```

  ```python Python theme={null}
  va = client.voice_agents.get("voice_agent_id")
  ```

  ```typescript TypeScript theme={null}
  const va = await client.voiceAgents.get("voice_agent_id");
  ```
</CodeGroup>

**Scope:** `voice_agents:read`  |  **Status:** `200 OK`

***

## Update a voice agent

PATCH semantics — only include fields you want to change. Null or absent
fields are not modified.

<CodeGroup>
  ```bash curl theme={null}
  curl -X PATCH https://api.yotel.in/api/v1/voice-agents/{voice_agent_id} \
    -H "Authorization: Bearer yt_live_YOUR_KEY" \
    -H "Content-Type: application/json" \
    -d '{"max_concurrent": 100}'
  ```

  ```python Python theme={null}
  va = client.voice_agents.update("voice_agent_id", max_concurrent=100)
  ```

  ```typescript TypeScript theme={null}
  const va = await client.voiceAgents.update("voice_agent_id", {
    max_concurrent: 100,
  });
  ```
</CodeGroup>

**Scope:** `voice_agents:write`  |  **Status:** `200 OK`

***

## Archive a voice agent

Soft-deletes the voice agent by setting `status: "archived"`. The UUID
remains valid for foreign-key references (existing calls, campaigns) but
new calls will not route to an archived agent.

<CodeGroup>
  ```bash curl theme={null}
  curl -X POST https://api.yotel.in/api/v1/voice-agents/{voice_agent_id}/archive \
    -H "Authorization: Bearer yt_live_YOUR_KEY"
  ```

  ```python Python theme={null}
  va = client.voice_agents.archive("voice_agent_id")
  ```

  ```typescript TypeScript theme={null}
  const va = await client.voiceAgents.archive("voice_agent_id");
  ```
</CodeGroup>

**Scope:** `voice_agents:write`  |  **Status:** `200 OK`

***

## Delete a voice agent

Hard-deletes the voice agent. Fails with `409` if the agent has active
sessions.

<CodeGroup>
  ```bash curl theme={null}
  curl -X DELETE https://api.yotel.in/api/v1/voice-agents/{voice_agent_id} \
    -H "Authorization: Bearer yt_live_YOUR_KEY"
  ```

  ```python Python theme={null}
  client.voice_agents.delete("voice_agent_id")
  ```

  ```typescript TypeScript theme={null}
  await client.voiceAgents.delete("voice_agent_id");
  ```
</CodeGroup>

**Scope:** `voice_agents:write`  |  **Status:** `204 No Content`

***

## Response fields

| Field                  | Type           | Description                              |
| ---------------------- | -------------- | ---------------------------------------- |
| `id`                   | string         | Voice agent UUID                         |
| `tenant_id`            | string         | Owning tenant                            |
| `name`                 | string         | Display name                             |
| `ws_url`               | string         | WebSocket endpoint                       |
| `auth_token`           | string \| null | Static auth token                        |
| `audio_format`         | object         | Audio encoding config                    |
| `external_agent_id`    | string \| null | Your cross-reference ID                  |
| `transfer_destination` | string \| null | Default transfer target                  |
| `max_concurrent`       | integer        | Concurrency limit                        |
| `status`               | string         | `"active"`, `"paused"`, or `"archived"`  |
| `token_lifetime`       | string         | `"30min_with_refresh"` or `"ws_session"` |
| `subprotocol`          | string         | WebSocket subprotocol                    |
| `ws_disconnect_action` | string         | `"hangup"` or `"transfer_to_queue"`      |
| `created_at`           | string         | ISO 8601                                 |
| `updated_at`           | string         | ISO 8601                                 |

***

## Errors

| Status | Condition                                                                |
| ------ | ------------------------------------------------------------------------ |
| `404`  | Voice agent not found or belongs to another tenant                       |
| `409`  | Cannot delete — active sessions exist (`VoiceAgentInUse`)                |
| `422`  | Validation error (e.g., invalid `ws_url`, `max_concurrent` out of range) |
