# Crear llamada web

**POST** `/v3/create-web-call`

Crea una llamada de voz que se realiza directamente desde el navegador, sin número de teléfono. La respuesta incluye el `access_token` y los datos de conexión que tu frontend le pasa al SDK de llamadas web para que el usuario se una a la llamada.

> ⚠️ **`/v2/create-web-call` deja de funcionar el 30 de septiembre de 2026.** Si tu integración todavía lo usa, sigue la [guía de migración a llamadas web v3](migrar-llamadas-web-v3.md).

---

## Parámetros del cuerpo

### Requeridos

| Campo | Tipo | Descripción |
|-------|------|-------------|
| `agent_id` | string | ID del agente que conducirá la llamada. Ejemplo: `agent_3f9c1a7b2e4d5c6f` |

### Opcionales

| Campo | Tipo | Descripción |
|-------|------|-------------|
| `agent_version` | integer | Versión específica del agente. Por defecto, la versión publicada más reciente. |
| `metadata` | object | Objeto libre para guardar información propia (ID de sesión, de usuario, etc.). Se recupera luego con [Obtener llamada](obtener-llamada.md). |
| `retell_llm_dynamic_variables` | object | Variables que se inyectan en el prompt del agente durante la llamada. Ejemplo: `{"nombre_cliente": "Ana"}` |

El cuerpo es el mismo que en la versión anterior: solo cambian la ruta y la respuesta.

---

## Respuesta — 201 Created

A diferencia de la versión anterior, la respuesta ya **no** trae el objeto completo de la llamada: trae solo lo necesario para conectarse. El detalle de la llamada (estado, transcripción, grabación, análisis) se consulta con [Obtener llamada](obtener-llamada.md) usando el `call_id`.

| Campo | Tipo | Descripción |
|-------|------|-------------|
| `call_id` | string | Identificador único de la llamada. Guárdalo para consultarla después. |
| `access_token` | string | Token para unirse a la llamada. Vence en pocos segundos si no se usa: créalo justo antes de conectar. |
| `transport` | string | Tipo de conexión que debe usar el SDK. Pásalo tal cual. |
| `url` | string | Dirección de conexión (según el `transport`). Pásala tal cual, si viene. |
| `ice_servers` | array | Servidores de conexión. Pásalos tal cual, si vienen. |

> 💡 Pasa **todos** los datos de conexión al SDK (`transport`, `url`, `ice_servers`, además del token). Si solo pasas el token, el SDK puede elegir otro tipo de conexión y la llamada no conecta.

---

## Ejemplo de solicitud

Desde **tu servidor** (nunca desde el navegador: tu API Key no debe quedar expuesta):

```bash
curl --request POST \
     --url https://calls.anunzi.net/v3/create-web-call \
     --header 'Authorization: Bearer anz_live_TU_API_KEY' \
     --header 'Content-Type: application/json' \
     --data '{
  "agent_id": "agent_3f9c1a7b2e4d5c6f",
  "retell_llm_dynamic_variables": {
    "nombre_usuario": "Carlos",
    "plan_actual": "Básico"
  },
  "metadata": {
    "session_id": "web-9923"
  }
}'
```

## Ejemplo de respuesta

```json
{
  "call_id": "Kx2pYnWVmlR3eDsT1Qva59fHgJzLcAXb",
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "transport": "gateway",
  "url": "wss://…",
  "ice_servers": [ { "urls": ["stun:…"] } ]
}
```

---

## Unirse a la llamada desde el navegador

Usa el SDK de llamadas web de Anunzi. Es un módulo JavaScript que se importa directamente desde nuestro dominio (no requiere instalar nada):

```html
<button id="llamar">Hablar con el agente</button>
<button id="colgar" disabled>Colgar</button>

<script type="module">
  import { VoiceClient } from 'https://panel.anunzi.net/voice/web-sdk.php';

  const client = new VoiceClient();

  client.on('call_started', () => console.log('Llamada iniciada'));
  client.on('call_ended',   () => console.log('Llamada terminada'));
  client.on('agent_start_talking', () => console.log('El agente habla'));
  client.on('agent_stop_talking',  () => console.log('El agente escucha'));
  client.on('error', (err) => { console.error(err); client.stopCall(); });

  document.getElementById('llamar').onclick = async () => {
    // 1) Tu backend crea la llamada con POST /v3/create-web-call y te devuelve la respuesta
    const r = await fetch('/mi-backend/crear-llamada-web', { method: 'POST' });
    const call = await r.json();

    // 2) Unirse pasando el token y TODOS los datos de conexión
    await client.startCall({
      accessToken: call.access_token,
      callId:      call.call_id,
      transport:   call.transport,
      url:         call.url,
      iceServers:  call.ice_servers,
    });
    document.getElementById('colgar').disabled = false;
  };

  document.getElementById('colgar').onclick = () => client.stopCall();
</script>
```

El navegador pide permiso de micrófono al iniciar la llamada. La página debe servirse por **HTTPS**.

### Eventos disponibles

| Evento | Cuándo ocurre |
|--------|---------------|
| `call_started` | La conexión se estableció y la llamada comenzó. |
| `call_ended` | La llamada terminó (colgó el usuario, el agente o por error). |
| `agent_start_talking` | El agente empieza a hablar (útil para animar la interfaz). |
| `agent_stop_talking` | El agente deja de hablar. |
| `error` | Error de conexión o de audio. Recomendado: llamar a `stopCall()`. |

Para la transcripción, el resumen y la grabación, consulta la llamada al terminar con [Obtener llamada](obtener-llamada.md).

---

## Códigos de estado

| Código | Descripción |
|--------|-------------|
| `201` | Llamada web creada correctamente. |
| `400` | Formato de solicitud inválido. Verifica los parámetros. |
| `401` | API Key ausente o inválida. |
| `402` | Período de prueba vencido. |
| `403` | El agente no pertenece a tu cuenta. |
| `422` | El agente solicitado no existe bajo tu API Key. |
| `429` | Límite de solicitudes alcanzado. |
| `500` | Error interno del servidor. |
