# Servicio VOIP

## Introducción

El servicio VOIP proporciona una API REST para administrar llamadas
telefónicas, consultar su estado e historial y realizar operaciones de
transferencia y finalización. Está dirigido a integradores que necesitan
interactuar con la plataforma de telefonía desde aplicaciones propias.

### Problema que resuelve

Permite iniciar y controlar llamadas mediante una interfaz HTTP
uniforme, desacoplando la lógica de telefonía de las aplicaciones
consumidoras.

### Casos de uso

-   Marcación saliente.
-   Consulta del progreso de una llamada.
-   Consulta del historial de eventos.
-   Transferencia entre extensiones, colas o números PSTN.
-   Finalización remota de llamadas.

### Alcance funcional

Incluye operaciones de consulta, marcación, transferencia y desconexión.
Además, dispone de un endpoint administrativo para consultar la
configuración de canales.

------------------------------------------------------------------------

# Endpoints

| Método | Ruta | Descripción |
|---|---|---|
| POST | [`/api/v1/dial/`](#iniciar-llamada) | Iniciar una llamada |
| GET | [`/api/v1/dial/{dial_id}/`](#consultar-llamada) | Consultar llamada |
| GET | [`/api/v1/status/{call_sid}/`](#consultar-estado-de-la-llamada) | Consultar estado de la llamada |
| GET | [`/api/v1/calls/{channel_id}/`](#listar-llamadas) | Listar llamadas |
| GET | [`/api/v1/call-logs/{call_sid}/`](#consultar-historial) | Consultar historial de la llamada |
| POST | [`/api/v1/transfer/`](#transferir-llamada) | Transferir llamada |
| POST | [`/api/v1/disconnect/`](#finalizar-llamada) | Finalizar llamada |
| POST | [`/api/v1/admin/channels/`](#consultar-información-de-canales) | Consultar información de canales (admin) |

## Autenticación

Depende de que al canal se le haya configurado la autenticación.

Las solicitudes requieren:

``` http
Authorization: {channel-authorization}
```

Las solicitudes **GET** aceptan la autenticación por url bajo el parámetro `auth`:

Ejemplo:

``` text
?auth={token}
```

## Manejo de errores

Cuando la operación falla, la respuesta es:

``` json
{
  "success": false,
  "message": "Descripción del error"
}
```

------------------------------------------------------------------------

## Iniciar llamada

**POST** `https://voice.induxsoft.net/api/v1/dial/`

Inicia una llamada saliente hacia un número o extensión, con soporte
para reintentos y espera entre intentos.

### Parámetros de ruta

No aplica.

### Parámetros de consulta

No aplica.

### Body

| Campo     | Tipo    | Obligatorio | Descripción |
|---|---|---|---|
| `channel` | string  | Sí          | Canal. |
| `from`    | string  | Sí          | Número origen o identificador de un pool de números. |
| `to`      | string  | Sí          | Número destino. |
| `ext`     | string  | Sí          | Extensión o cola. |
| `say`     | string  | No          | Mensaje al conectar. |
| `attemps` | integer | No          | Intentos. Valor por defecto: 1. |
| `delay`   | integer | No          | Espera entre intentos en segundos. |

### Ejemplo de solicitud

```http
POST https://voice.induxsoft.net/api/v1/dial/
Authorization: {channel-authorization}
Content-Type: application/json

{
  "channel":"channel01",
  "from":"pool01",
  "to":"+52 123 456 7890",
  "ext":"100",
  "say":"Hola",
  "attemps":2,
  "delay":5
}
```

### Ejemplo de respuesta

``` json
{
  "success": true,
  "message": "Marcando...",
  "dial": "Token de la solicitud de marcación"
}
```

------------------------------------------------------------------------

## Consultar llamada

**GET** `https://voice.induxsoft.net/api/v1/dial/{dial_id}/`

Devuelve la información actual de la llamada asociada al identificador
de marcación.

### Parámetros de ruta

| Parámetro | Descripción |
|---|---|
| `dial_id` | Token de la solicitud de marcación, obtenido en la respuesta de `/api/v1/dial/`. |

### Parámetros de consulta

No aplica (excepto `auth`, ver [Autenticación](#autenticacion)).

### Body

No aplica.

### Ejemplo de solicitud

```http
GET https://voice.induxsoft.net/api/v1/dial/8f3a1c2b-token-de-marcacion/
Authorization: {channel-authorization}
```

### Ejemplo de respuesta

``` json
{
  "start": "2026-07-10 12:40:00",
  "timestamp": "2026-07-10 12:41:15",
  "channel_id": "channel01",
  "from": "+52 123 456 7891",
  "to": "+52 123 456 7890",
  "ext": "100",
  "duration": 75,
  "direction": "outbound",
  "call_sid": "CA1234567890abcdef1234567890abcdef",
  "status": "in-progress",
  "message": "Marcando..."
}
```

------------------------------------------------------------------------

## Consultar estado de la llamada

**GET** `https://voice.induxsoft.net/api/v1/status/{call_sid}/`

Devuelve el estado actual y la información principal de la llamada.

### Parámetros de ruta

| Parámetro | Descripción |
|---|---|
| `call_sid` | Identificador de la llamada proporcionado por el proveedor. |

### Parámetros de consulta

No aplica (excepto `auth`, ver [Autenticación](#autenticacion)).

### Body

No aplica.

### Ejemplo de solicitud

```http
GET https://voice.induxsoft.net/api/v1/status/CA1234567890abcdef1234567890abcdef/
Authorization: {channel-authorization}
```

### Ejemplo de respuesta

``` json
{
  "status": "in-progress",
  "message": "Marcando...",
  "direction": "outbound",
  "start": "2026-07-10 12:40:00",
  "timestamp": "2026-07-10 12:41:15",
  "from": "+52 123 456 7891",
  "to": "+52 123 456 7890",
  "ext": "100",
  "call_sid": "CA1234567890abcdef1234567890abcdef"
}
```

> `status` puede tomar los valores: `queued`, `ringing`, `in-progress`,
> `completed`, `busy`, `failed`, `no-answer` o `canceled`.

------------------------------------------------------------------------

## Listar llamadas

**GET** `https://voice.induxsoft.net/api/v1/calls/{channel_id}/`

Devuelve un arreglo `data` con las llamadas encontradas para el canal
indicado, aplicando los filtros de consulta proporcionados.

### Parámetros de ruta

| Parámetro | Descripción |
|---|---|
| `channel_id` | Identificador del canal. |

### Parámetros de consulta

| Parámetro | Descripción |
|---|---|
| `ext`  | Filtrar por extensión. |
| `sd`   | Fecha inicial. |
| `ed`   | Fecha final. |
| `last` | Últimos N registros. |

### Body

No aplica.

### Ejemplo de solicitud

```http
GET https://voice.induxsoft.net/api/v1/calls/channel01/?ext=100&sd=2026-07-01&ed=2026-07-10&last=20
Authorization: {channel-authorization}
```

### Ejemplo de respuesta

``` json
{
  "success": true,
  "message": "",
  "data": [
    {
      "start": "2026-07-10 12:40:00",
      "timestamp": "2026-07-10 12:41:15",
      "channel_id": "channel01",
      "from": "+52 123 456 7891",
      "to": "+52 123 456 7890",
      "ext": "100",
      "duration": 75,
      "direction": "outbound",
      "call_sid": "CA1234567890abcdef1234567890abcdef",
      "status": "completed",
      "message": "Marcando..."
    }
  ]
}
```

------------------------------------------------------------------------

## Consultar historial

**GET** `https://voice.induxsoft.net/api/v1/call-logs/{call_sid}/`

Devuelve la bitácora cronológica de la llamada.

### Parámetros de ruta

| Parámetro | Descripción |
|---|---|
| `call_sid` | Identificador de la llamada proporcionado por el proveedor. |

### Parámetros de consulta

No aplica (excepto `auth`, ver [Autenticación](#autenticacion)).

### Body

No aplica.

### Ejemplo de solicitud

```http
GET https://voice.induxsoft.net/api/v1/call-logs/CA1234567890abcdef1234567890abcdef/
Authorization: {channel-authorization}
```

### Ejemplo de respuesta

``` json
{
  "success": true,
  "message": "",
  "data": [
    {
      "created": "2026-07-10 12:44:00",
      "ext": "100",
      "note": ""
    }
  ]
}
```

------------------------------------------------------------------------

## Transferir llamada

**POST** `https://voice.induxsoft.net/api/v1/transfer/`

Transfiere una llamada en curso hacia otra extensión, cola o número
PSTN, con posibilidad de definir un destino alternativo (`fallback`)
en caso de que la transferencia falle.

### Parámetros de ruta

No aplica.

### Parámetros de consulta

No aplica.

### Body

| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `call_sid` | string | Sí | Identificador de la llamada. |
| `to` | string | Sí | Número de destino, extensión o cola. |
| `say` | string | No | Mensaje al conectar. |
| `fallback` | string | No | Número o extensión si falla la transferencia. |

### Ejemplo de solicitud

```http
POST https://voice.induxsoft.net/api/v1/transfer/
Authorization: {channel-authorization}
Content-Type: application/json

{
  "call_sid": "CA1234567890abcdef1234567890abcdef",
  "to": "200",
  "say": "Te transfiero con soporte.",
  "fallback": "100"
}
```

### Ejemplo de respuesta

``` json
{
  "success": true,
  "message": "Marcando..."
}
```

------------------------------------------------------------------------

## Finalizar llamada

**POST** `https://voice.induxsoft.net/api/v1/disconnect/`

Finaliza de forma remota una llamada en curso.

### Parámetros de ruta

No aplica.

### Parámetros de consulta

No aplica.

### Body

| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `call_sid` | string | Sí | Identificador de la llamada. |
| `goodbye` | string | No | Mensaje al desconectar. |

### Ejemplo de solicitud

```http
POST https://voice.induxsoft.net/api/v1/disconnect/
Authorization: {channel-authorization}
Content-Type: application/json

{
  "call_sid": "CA1234567890abcdef1234567890abcdef",
  "goodbye": "Gracias por su llamada."
}
```

### Ejemplo de respuesta

``` json
{
  "success": true,
  "message": "Colgando..."
}
```

------------------------------------------------------------------------

# Administración

## Consultar información de canales

**POST** `https://voice.induxsoft.net/api/v1/admin/channels/`

Servicio de uso exclusivamente administrativo.

Recibe un objeto cuyas claves son identificadores de canal y los valores
corresponden a sus credenciales. La respuesta contiene la configuración
completa de extensiones IVR, agentes IA, colas y destinos PSTN para cada
canal solicitado.

### Parámetros de ruta

No aplica.

### Parámetros de consulta

No aplica.

### Body

Objeto dinámico donde cada clave es un `channel_id` y cada valor es su
`channel_authorization` correspondiente.

| Campo | Tipo | Obligatorio | Descripción |
|---|---|---|---|
| `{channel_id}` | string | Sí | Autorización (`channel_authorization`) del canal indicado como clave. Puede incluirse más de un canal en la misma solicitud. |

### Ejemplo de solicitud

```http
POST https://voice.induxsoft.net/api/v1/admin/channels/
Content-Type: application/json

{
  "channel01": "channel01-authorization-token"
}
```

### Ejemplo de respuesta

``` json
{
  "channel01": {
    "extensions": {
      "_default": {
        "type": "ivr",
        "play": "https://site.example/assets/vmsg-1.mp3",
        "dtmf": "dtmf",
        "timeout": 1,
        "numDigits": 1,
        "actionOnEmptyResult": "true",
        "action": "101"
      },
      "101": {
        "type": "aia",
        "agent": "agent-001",
        "voice": "es-MX-voice-01",
        "language": "es-ES",
        "greeting": "Hola, mi nombre es Ana",
        "ws": "wss://rtc.induxsoft.net/channels/ws/channel01",
        "action": "https://voice.induxsoft.net/handlers/twilio/disconnect"
      },
      "200": {
        "type": "queue",
        "members": "201, 202, 203",
        "timeout": 10,
        "strategy": "linear"
      },
      "201": {
        "type": "pstn",
        "to": "+52 123 456 7890",
        "voice": "provider.voice",
        "language": "es-ES",
        "say": "Te comunico con Juan, por favor espera."
      }
    }
  }
}
```

#### Tipos de extensión

| Tipo | Descripción |
|---|---|
| `ivr` | Menú de respuesta interactiva. Reproduce un audio (`play`) y captura DTMF según `dtmf`, `timeout` y `numDigits`, derivando a `action`. |
| `aia` | Agente de IA conversacional, conectado vía WebSocket (`ws`) con voz e idioma configurables. |
| `queue` | Cola de atención con una lista de `members` (extensiones) y una `strategy` de distribución. |
| `pstn` | Destino hacia un número telefónico externo (`to`), con mensaje de conexión (`say`). |