NAV
cURL PHP Python

API Voice v1.0

Bienvenido a la documentación de API Voice v1.0 de netelip.

API Voice facilita a tus aplicaciones WEB el control en vivo de tus llamadas de teléfono, tanto entrantes como salientes, permitiéndote realizar acciones sobre estas en función de lo que el llamante o llamado diga o marque en el teclado de su teléfono. Podrás montar fácilmente servicios telefónicos de reservas, gestión de cobros, control de acceso a IVRs, encuestas telefónicas, etc

Tenemos ejemplos en lenguajes de shell, php y python que pueden ver en el área oscura de la derecha. Puede cambiar el lenguaje de programación de los ejemplos en las pestañas que aparecen arriba a la derecha.

Para conocer todas las APIs disponibles, información general y restricciones aplicadas a su uso consulte "Documentación APIs".

¿Qué necesito para utilizar API Voice?

Solo necesitarás tener una cuenta de cliente de netelip con el servicio API Voice activo, y un servidor WEB en el que correrán las aplicaciones que establecerán las comunicaciones con API Voice de netelip.

Si todavía no es cliente de netelip puede registrarse en el siguiente enlace.

¿Cómo funciona API Voice?

API Voice v1.0 de netelip tiene un conjunto de comandos que se utilizan para indicar a netelip qué hacer cuando se realiza o se recibe una llamada a través de API Voice.

Cuando alguien hace una llamada a uno de tus números de teléfono de API Voice, buscaremos la "URL de control para llamadas entrantes" asociada a ese número de teléfono, y se hará una petición a dicha URL, facilitando información de la llamada entrante y esperando recibir instrucciones sobre qué hacer con la llamada.

Algunas de las instrucciones disponibles son:

También se podrán realizar otras acciones si dispones del servicio vPBX, como:

Así mismo, tus aplicaciones podrán lanzar llamadas a números de teléfono de la red telefónica pública, a través de envío de un POST con autentificación por Token + IP (si lo especifica). Una vez contestada la llamada, esta pasará a ser gestionada por la “URL de control para llamadas salientes” de su servidor WEB.

Puede consultar la lista completa de comandos en el apartado "Comandos disponibles".

Funcionalidades

Las aplicaciones de API Voice v1.0 de netelip son muchas pero las funcionalidades principales son:

El control de las llamadas se realizará a través de las "URLs de control de llamadas" ubicadas en su servidor WEB.

Estas URLs realizarán las comprobaciones o tareas programadas a su interés, y enviarán a API Voice los comandos a ejecutar para la llamada en curso.

Cuando API Voice finalice la ejecución de un comando, conectará con su URL de control para indicar el resultado del comando previo, y mantendrá la llamada activa a la espera de recibir el siguiente comando a ejecutar.

Este comportamiento se repetirá indefinidamente hasta que alguno de los extremos cuelgue la llamada en curso, ya sea tu URL de control mediante el comando de colgado, o el llamante o llamado mediante la tecla de colgado de tu terminal telefónico.

Para ver como se implementa un servicio para controlar las "URLS de control de llamadas" consulte el apartado "Controlador de llamadas".

Puede consultar la lista completa de comandos en el apartado "Comandos disponibles" y ver un caso práctico en el apartado "Caso práctico: flujo".

API Voice de netelip ofrece la opción de enviar el estado de las llamadas realizadas a una "URL de reporte de llamadas".

Debe configurar su "URL de reporte de llamadas" en su panel de control de API Voice, inserta la dirección web donde recibir el registro de llamadas realizadas/recibidas.

Para ver como se implementa un servicio para gestionar la información de llamadas consulte el apartado "Informe de llamadas".

El control de notificaciones de eventos de llamadas se realizará a través de la "URL enventos de llamadas" ubicada en su servidor WEB.

Esta URL realizará las comprobaciones y gestión de los eventos según su interés.

Para ver como se implementa un servicio para gestionar las notificacieones consulte el apartado "Notificaciones de estados".

Activar vPBX para API Voice

Para controlar las llamadas que realizan las extensiones de tu vPBX a través de API Voice, tiene que acceder al panel de control de netelip, sección "vPBX", editar una extensión e indicarle que la extensión va a utilizar el Plan de marcado API Voice y seleccionar uno de nuestros API Voice disponibles.

Seguridad

En este apartado se describen los mecanísmos de seguridad y algunas recomendaciones.

Autentificación

Todos los ejemplos de la documentación se basan en este esqueleto:

# Asegurese de pasar siempre las cabeceras correctamente.
curl -X POST https//api.netelip.com/v1/voice/{endpoint} \
  --data "token=69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz"
<?php
$url="https://api.netelip.com/v1/voice/{endpoint}";
$post = array(
   "token" => "69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz",
);

$request = curl_init($url);
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_TIMEOUT, 180);
curl_setopt($request, CURLOPT_POSTFIELDS, $post);
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);

$response = curl_exec($request);
if ($response !== false) {
   // Manejar datos devueltos por la petición
} else {
   // Manejar error de conexión
}

curl_close($request);
?>
#!/usr/bin/env python

import requests

url = 'https://api.netelip.com/v1/voice/{endpoint}'
data = {
    'token': '69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz',
}

response = requests.post(url=url, data=data)

if response:
    # Manejar datos devueltos por la petición
else:
    # Manejar error de conexión

Reemplazar {endpoint} por el punto de entrada correcto.
El token usado es un token de ejemplo no válido.

API Voice de netelip usa autentificación por token, para obtener su token acceda a 'Token de seguridad' que encontrará en su 'Panel de control' en sección datos personales.

Si todavía no es cliente de netelip puede registrarse en el siguiente enlace.

API Voice de netelip espera en todas sus peticiones que se autentifique con un token similar a este:

69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz

Redes de confianza.

Para usar el servicio de API Voice v1.0 de netelip es necesario que desarrolle servicios (controladores) en sus propios servidores y esto supone tener abierto los servicios al público.

Se recomienda filtrar los accesos mediante IPs de confianza.
Las redes de confianza de netelip son:

Datacenter Network
Europa 185.8.244.0/24
América 192.99.91.144/29

HTTPS

La comunitcación entre API Voice v1.0 de netelip y sus servidores se realiza mediante los protocolos HTTP y HTTPS.

netelip recomienda siempre el uso de HTTPS para garantizar que la comunicación entre sus servidores y API Voice viaje en un canal cifrado.

netelip no aplica restricciones en cuanto al uso de certificados autofirmados.

Controlador de llamadas

Ejemplo de controlador de llamadas que pide un código de usuario para poder acceder al menú

# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación. 
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
// Obtenemos los datos de la llamada y las guardamos en variables
$src = $_POST["src"];
$dst = $_POST["dst"];
$id = $_POST["ID"];

if ($src == "" || $dst == "" || $id != "") die(); // Algo está mal, terminamos

$dtmf = $_POST["dtmf"];

// Datos del ultimo comando ejecutado si no estamos al comienzo de una llamada
$command = $_POST["command"];
$options = $_POST["options"];
$userfield = ($_POST["userfield"] == "") ? "1" : $_POST["userfield"];

$messages = array(
    1 => "Bienvenido a mi empresa, por favor escriba a continuacion su usuario.",
    2 => "Su usuario es correcto, accedemos al menu del servicio.",
    3 => "Su usuario es incorrecto, para acceder a este servicio debes de ser usuario.",
    4 => "Pulse uno para hablar con atencion al cliente, pulse dos, para hablar con soporte.",
);

switch($userfield) {

   case "0": // colgamos la llamada
      $command = "hangup";
      $options = "";
      $userfield = "";
      break;

   case "1": // reproducimos una locucion esperando una respuesta
      $command = "speak_getdtmf";
      $options  = "google;es;".$messages[1].";5000;4;1.2";
      $userfield = "2";
      break;

   case "2":
      $command = "speak_getdtmf";
      switch($dtmf) {

         case "timeout": // tiempo agotado, locucion y repetimos
            $options = "netelip;Pedro;".$messages[1].";5000;4";
            $userfield = "2";
            break;

         case("1111"): // usuario correcto, locucion y a la cola
            $options = "netelip;Pedro;".$messages[2].$messages[4].";5000;1";
            $userfield = "3";
            break;

         default: // usuario incorrecto, locución de despedida y colgamos
            $command = "speak";
            $options = "netelip;Pedro;".$messages[3];
            $userfield = "0";
         }
      }
      break;

   case "3":
      $command = "queue";
      $userfield = "0";
      switch($dtmf) {

         case "timeout": // tiempo agotado, locucion y repetimos
            $command = "speak_getdtmf";
            $options = "netelip;Pedro;".$messages[4].";5000;1";
            $userfield = "3";
            break;

         case "1": // ejecutamos la cola de atencion de la vPBX con prioridad 2
            $options = "colaatencion;2";
            break;

         case "2": // ejecutamos la cola de soporte de la vPBX con prioridad 1
            $options = "colasoporte;1";
            break;
      }
      break;
}

$cadena = array("command"=>$comand, "options"=>$options, "userfield"=>$userfield);
echo(json_encode($cadena));
?>
#!/usr/bin/env python

messages = [
    'Bienvenido a mi empresa, por favor escriba a continuacion su usuario.',
    'Su usuario es correcto, accedemos al menu del servicio.',
    'Su usuario es incorrecto, para acceder a este servicio debes de ser usuario.',
    'Pulse uno para hablar con atencion al cliente, pulse dos, para hablar con soporte.',
]

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/controller', methods=['GET','POST'])
def controller():

    if request.method == 'POST':
        # Obtenemos los datos de la llamada y las guardamos en variables
        src = request.form.get('src')
        dst = request.form.get('dst')
        idc = request.form.get('ID')

        if src == None or dst == None or idc == None: 
            return jsonify(error='No se han definido argumentos')
        if src == "" or dst == "" or idc == "": 
            return jsonify(error='Los argumentos no pueden ir vacios')

        dtmf = request.form.get("dtmf")

        # Datos del ultimo comando ejecutado
        c = {
            'command'  : request.form.get("command"),
            'options'  : request.form.get("options"),
            'userfield': request.form.get("userfield")
        }

        if c['userfield'] == "0": # colgamos la llamada
            c['command'] = "hangup"
            c['options'] = ""
            c['userfield'] = ""

        elif c['userfield'] == "1" or c['userfield'] == "" or c['userfield'] == None: 
            # reproducimos una locucion esperando una respuesta (llamada entrante)
            c['command'] = "speak_getdtmf"
            c['options'] = "google;es;%s;5000;4;1.2" % messages[0]
            c['userfield'] = "2"

        elif c['userfield'] == "2":
            c['command'] = "speak_getdtmf"

            if dtmf == "timeout": # tiempo agotado, locucion y repetimos
                c['options'] = "netelip;Pedro;%s;5000;1" % messages[0]
                c['userfield'] = "2"

            elif dtmf == "1111": # usuario correcto, locucion y a la cola
                c['options'] = "netelip;Pedro;%s%s;5000;1" % (messages[1], messages[3])
                c['userfield'] = "3"

            else: # usuario incorrecto, locución de despedida y colgamos
                c['command'] = "speak"
                c['options'] = "netelip;Pedro;%s" % messages[2]
                c['userfield'] = "0"

        elif c['userfield'] == "3":
            c['command'] = "queue"
            c['userfield'] = "0"

            if dtmf == "timeout": # tiempo agotado, locucion y repetimos
                c['command'] = "speak_getdtmf"
                c['options'] = "netelip;Pedro;%s;5000;1" % messages[3]
                c['userfield'] = "3"

            elif dtmf == "1": # ejecutamos la cola de atencion de la vPBX con prioridad 2
                c['options'] = "colaatencion;2"

            elif dtmf == "2": # ejecutamos la cola de soporte de la vPBX con prioridad 1
                c['options'] = "colasoporte;1"

        print(jsonify(c))
        return jsonify(c)
    else:
        return jsonify(error='Metodo no permitido') 

if __name__ == '__name__':
    app.run()

Para controlar las llamadas que entran en su servicio de API Voice necesita desarrollar un controlador que gestione todas las peticiones que API Voice envíe a su "URLs de control de llamadas".

El código de este controlador puede estar escrito en cualquier lenguaje de programación web ya que la comunicación entre su servidor WEB y API Voice es mediante peticiones HTTP de tipo POST (Content-Type: text/html).

API Voice se comunicará con su servidor WEB mediante método HTTP POST o Secure HTTP POST, enviando a su URL de control los datos de la llamada y el resultado del comando ejecutado.

Una vez que API Voice realice una petición a su URL de control este quedará a la espera de que su URL de control conteste con el siguiente comando a ejecutar.

Petición

Contenido de la variable POST cuando se recibe un llamada y API Voice realiza la petición a su controlador:

{
   "ID": "1576556033.1735",
   "api": "Mi API",
   "src": "638829213",
   "dst": "34951504990",
   "startcall": "2019-11-12 11:04:26",
   "typesrc": "did",
   "usersrc": "638829213"
}

Las posibles variables que se incluirán en la petición POST cuando API Voice conecte con su URL de control serán:

Clave Descripción
ID ID único de la llamada
api Nombre del API destino de la llamada
src Número de origen de la llamada
dst Número de destino de la llamada
startcall Fecha y hora en la que comenzó la llamada
durationcall Duración actual de la llamada
durationcallanswered Duración de la llamada una vez atendida por un agente
command Comando ejecutado
options Opciones del comando ejecutado
description Descripción del resultado de la ejecución del comando
statuscode Código de estado de la ejecución
statuscall Estado de la llamada, ver valores
userfield Variable establecida por el usuario
userdata Variable opcional reservada para el usuario.
typesrc Tipo de origen, ver valores
usersrc Usuario del origen de la llamada, ver valores
diversion Información sobre el desvío de llamada, si existiera. Sólo para llamadas entrantes, ver información

statuscall

Posibles valores de statuscall:

Valor Descripción
CHANUNAVAIL El número llamado no existe
BUSY El número llamado está ocupado
NOANSWER El número llamado no contesta
ANSWER El número llamado ha contestado
CANCEL El número llamado ha colgado
CONGESTION Fallo en red telefónica por congestión
UNKNOW Fallo en red telefónica desconocido

typesrc

Posibles valores de typesrc:

Valor Descripción
ext Llamada con origen una extensión de tu vPBX cuando ésta tiene el asociado el "Plan de marcado de API Voice".
did Llamada con destino un número de teléfono de netelip gestionado por API Voice.

usersrc

Este valor depende directamente de la clave typesrc.

Si typesrc es "ext", el valor de usersrc será el usuario SIP de la extensión que realiza la llamada.

Y si typesrc es "did" el valor de usersrc será el número de teléfono de origen de la llamada, tendrá el mismo valor que src.

diversion

Muestra información sobre el desvío de llamada si existiera, mostrando el número de teléfono llamado originariamente y la causa del desvío.

El valor de este campo tiene la siguiente estructura:

n_telefono;reason=razón

siendo n_telefono, el número de teléfono llamado originariamente; y razón, la causa del desvío de la llamada.

Ejemplo:

El usuario A llama a usuario B y este se desvía al número de teléfono de APIVoice, APIVoice mostrará como src el número de teléfono del usuario A y diversion tendrá el valor del número de teléfono del usuario B más la causa del desvío de llamada.

Respuesta

Ejemplo de una respuesta a API Voice:

{
   "command": "speak",
   "options": "netelip;Pedro;Espere por favor.",
   "userfield":"2;espera;200"
}

API Voice quedará a la espera de que su URL de control conteste con el siguiente comando a ejecutar, siempre que la variable statuscall se mantenga con valor ANSWER o sea la primera petición de recepción de llamada.

Su URL de control debe responder con una cadena de texto con estructura json indicando el comando u orden que API Voice debe ejecutar (command), las opciones de configuración del comando (options) y datos personalizados que puede indicar el controlador (userfield).

Una vez procesado el comando API Voice volverá a conectar con su URL de control para indicarle el estado de la llamada y esperará a la siguiente orden.

Este proceso ser repetirá hasta que la llamada termine.

Puede consultar la lista completa de comandos y su configuración en el apartado "Comandos disponibles".

Lanzador de llamadas

Ejemplo de petición de llamada:

curl -X POST https://api.netelip.com/v1/voice \
  --data "token=69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz" \
  --data "api=Mi API" \
  --data "src=34951223344" \
  --data "dst=0034666554433" \
  --data "duration=30" \
  --data "typedst=pstn"
<?php
$url="https://api.netelip.com/v1/voice";
$post = array(
   "token"     => "69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz",
   "api"       => "Mi API",
   "src"       => "34951223344",
   "dst"       => "0034666554433",
   "duration"  => "30",
   "typedst"   => "pstn",
);

$request = curl_init($url);
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($request, CURLOPT_POSTFIELDS, $post);
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);

$response = curl_exec($request);
$response_code = curl_getinfo($request, CURLINFO_HTTP_CODE);
if ($response !== false) {
   if ($response_code == 200) {
      echo $response;   
   }
} else {
   echo "Error: ".$response_code;
}

curl_close($request);
?>
#!/usr/bin/env python

import requests

url = 'https://api.netelip.com/v1/voice'
data = {
    'token'    : '69cizi7zc2394b9f84e97e78b8913d0ie1z2i6b58iec943fbz478z13c00d59cz',
    'api'      : 'Mi API',
    'src'      : '34951223344',
    'dst'      : '0034666554433',
    'duration' : '30',
    'typedst'  : 'pstn',
}

response = requests.post(url=url, data=data, timeout=(5, 5), max_redirects=3)

if response:
    if response.status_code == 200:
        print(response.text)
else:
    print("Error: %s" % $response.status_code)

Para realizar una llamada a través de API Voice solo es necesario enviar a la URL, 'https://api.netelip.com/v1/voice', mediante método POST, los siguientes datos:

Clave Descripción
api Nombre de la API a utilizar.
token Palabra de seguridad asociada a la API a utilizar.
src Identificador de llamada que se mostrará al usuario que recepciona la llamada.
dst Número de teléfono a llamar.
duration Duración máxima del intento de llamada en segundos. Entre 1 y 60.
userdata Variable opcional reservada para el usuario.
typedst Tipo de destino de la llamada, ver valores

typedst

Posibles valores de typedst:

Valor Descripción
pstn Llamada hacia la red pública.
extension Llamada hacia una extensión de tu vpbx.

Llamada rechazada

Respuesta de llamada rechazada:

{
    "response": "400"
}

API Voice podrá rechazar la llamada con un código 400 (unauthorized) en formato json, si el token enviado o la IP desde la que se origina la petición no es válida.

Llamada aceptada

Respuesta de llamada aceptada:

{
    "response": "200",
    "ID": "1576556033.1735"
}

Si API Voice acepta la llamada lo indicará con un código 200 (OK) y el ID único de la llamada a través de una cadena con estructura json.

El resultado del lanzamiento de la llamada se enviará a su URL de control de llamadas como se indica en el apartado "Controlador de llamadas - Petición".

La petición se realizará con la siguiente información:

Clave Descripción
ID ID único de la llamada
api Nombre del API destino de la llamada
src Número de origen de la llamada
dst Número de destino de la llamada
startcall Fecha y hora en la que comenzó la llamada
statuscall Estado de la llamada, ver valores

De este modo, tu URL de control llamadas salientes tomará el control de la llamada en curso y podrá contestar a API Voice con el siguiente comando a ejecutar como se indica en el apartado "Controlador de llamadas - Respuesta".

Puede consultar la lista completa de comandos y su configuración en el apartado "Comandos disponibles".

Destino no contesta

En caso de responder el lanzador de llamadas satisfactoriamente pero el destinatario no coger la llamada, se devolverá el estado de tal llamada a la URL de control de llamadas salientes, con la siguiente información:

Clave Descripción
ID ID único de la llamada
token Token que se utilizó en el lanzador de llamadas
api Nombre del API destino de la llamada
src Número de origen de la llamada
dst Número de destino de la llamada
duration Duración del ring de la llamada
typedst Tipo de destino de la llamada
userdata Variable establecida por el usuario
startcall Fecha de la llamada
statuscall Estado de la llamada

Para ver como API Voice trata las peticiones consultar el apartado "Controlador de llamadas - Respuesta".

Puede consultar la lista completa de comandos y su configuración en el apartado "Comandos disponibles".

Integraciones

La realización de llamadas puede ser ejecutada desde una aplicación de escritorio o web, solo es necesario que la aplicación integre el protocolo de comunicación HTTPS.

Puede consultar todos los ejemplos de esta API para ver como se realizan peticiones HTTP con curl, php y python.

Informe de llamadas

Ejemplo para almacenar en un fichero la información de las llamadas:

# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación. 
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
$file = "calls.csv";
$linecall = "";

$calls = json_decode($_POST["calls"], true);

//recorremos las llamadas
foreach($calls as $call){
   // recorremos cada uno de los valores de la llamada para montar una linea csv
   foreach($call as $value) {
      $linecall = $linecall.";".$value;
   }
   $linecall=$linecall."\n";
}

// añadimos la linea de registro de la llamada a nuestro fichero de llamadas
file_put_contents($file, $linecall, FILE_APPEND);
?>
#!/usr/bin/env python

import json
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/reporter', methods=['GET','POST'])
def controller():

    if request.method == 'POST':

        calls = json.loads(request.form.get('calls'))
        with open('calls.csv', 'a') as f:
            for call in calls:
                line = ','.join(call.values()) + '\n'
                f.write(line)

        return jsonify(calls=len(calls))
    else:
        return jsonify(error='Metodo no permitido')

if __name__ == '__name__':
    app.run()

Para gestionar la información de las llamadas que entran en su servicio de API Voice necesita desarrollar un controlador que gestione todas las peticiones que API Voice envíe a su "URL de reporte de llamadas".

El código de este controlador puede estar escrito en cualquier lenguaje de programación web, ya que la comunicación entre su servidor WEB y API Voice es mediante peticiones HTTP de tipo POST con una estructura "json".

API Voice se comunicará periódicamente con su servidor WEB mediante método HTTP POST o Secure HTTP POST, enviando a su "URL de reporte de llamadas" los datos de las llamadas del último periódo y el resultado del comando ejecutado.

Informe

Ejemplo de dos registros (genérico y vPBX) en el array 'calls':

[
 ...
 {
   "ID": "",
   "startdate": "2020-04-23 12:17:40.897837",
   "stopdate": "2020-04-23 12:17:45.897837",
   "src": "667001122",
   "dst": "34915221100",
   "dstname": "",
   "duration": "5", 
   "cost":0,
   "status": "answer",
   "ip": "",
   "useragent": "",
   "plan":""
 },
 ...
 {
   "ID": "",
   "startdate": "2020-04-23 12:29:01.47034",
   "stopdate": "2020-04-23 12:29:06.47034",
   "src": "34815111000 (Ext 101)","dst":"666334455",
   "dstname": "Espa\\u00f1a - m\\u00f3vil",
   "duration": "5",
   "cost": 0.0024,
   "status": "answer",
   "ip": "192.168.1.33",
   "useragent": "MyAgent\\/SPA333-1.2.3","plan":""
 }
 ...
]

El registro de llamadas se enviará a la "URL de reporte de llamadas" mediante método POST y se entregará una lista con indice "calls" en formato "json".

La estructura de los registros de la lista en "json" que API Voice entregará al conectar con su "URL de reporte de llamadas" será:

Clave Descripción
startdate Fecha de inicio de la llamada.
stopdate Fecha de finalización de la llamada.
src Origen de la llamada.
dst Destino de la llamada.
dstname Nombre del destino de la llamada.
cost Coste de la llamada.
status Estado de la llamada.
ip IP del dispositivo desde la que ha realizado la llamada
duration Duración de la llamada.
useragent Nombre del dispositivo que ha realizado la llamada.
plan Plan de llamadas utilizado en la llamada.

Notificaciones de estado

Ejemplo para gestionar las notificaciones:

# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación. 
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
$call = json_decode($_POST["call"], true);

switch ($call['status']) {
   case 'ring':
      ...
      break;
   case 'answer':
      ...
   case 'hangup':
      ...
      break;
   case 'busy':
      ...
      break;
   case 'noanswer':
      ...
      break;
   case 'notavailable':
      ...
      break;
}
?>
#!/usr/bin/env python

import json
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/notifications', methods=['POST'])
def controller():

    if request.method == 'POST':

        call = json.loads(request.form.get('call'))
        if call['status'] == 'ring':
            ...
        elif call['status'] == 'answer':
            ...
        elif call['status'] == 'hangup':
            ...
        elif call['status'] == 'busy':
            ...
        elif call['status'] == 'noanswer':
            ...
        elif call['status'] == 'notavailable':
            ...

        return jsonify(call=len(call))
    else:
        return jsonify(error='Metodo no permitido')

if __name__ == '__name__':
    app.run()

Las notificaciones de estado de extensiones en vPBX, permiten comunicar los cambios de estado de su extensiones, indicando cuando una llamada ha sido contestada, colgada, cancelada, etc, en sus extensiones. Estas notificaciones se realizaran a una URL de control ("URL eventos de llamada" o "URL eventos de registro") y que usted definirá y programara en sus servidores.

El código del manejador de su URL de control puede estar escrito en cualquier lenguaje de programación web, ya que la comunicación entre su servidor WEB y API Voice es mediante peticiones HTTP de tipo POST con una estructura "json".

API Voice se comunicará con su servidor WEB cada vez que se produzca un evento mediante método HTTP POST o Secure HTTP POST, enviando a su URL de control los datos del evento.

Notificación de llamadas

Ejemplo de contenido del índice 'call' de la variable POST cuando se envía una notificación a su URL de notificación de eventos en llamadas:

{
   "uniqueid": "1576556033.1735",
   "src": "638829213",
   "dst": "34951504990",
   "userexten": "7491464423100",
   "status": "ring",
   "date": "2020-04-21",
   "time": "10:44:10",
   "type": "inbound",
   "idapivoice": "1600429592.18200"
}

Los eventos de las llamadas se enviará a la url "URL eventos de llamada" mediante método POST con el índice "call" en formato "json".

La estructura de comunicación "json" será:

Clave Descripción
uniqueid ID de llamada único
src Origen de la llamada
dst Destino de la llamada
userexten Usuario SIP de la extensión que notifica el evento
status Estado del evento. Valores: ring, answer, hangup, busy, noanswer o notavailable
date Fecha del evento, con formato YYYY-MM-DD
time Hora del evento, con formato HH:MM:SS. La hora se presentará en la zona horaria GMT
type Tipo de llamada. Valores: inbound o outbound
transferid ID de llamada transferida, aparecerá cuando se transfiere la llamada a otra extensión
transferuserexten usuario SIP de la extensión que transfiere la llamada, aparecerá cuando se transfiere la llamada a otra extensión
idapivoice ID de llamada único de API Voice. Este valor solo aparecerá cuando la llamada provenga de hacer una llamada desde el lanzador de API Voice o recibida a traves de API Voice y transferidas a vPBX.
viacall Indica que la llamada recibida en tu extensión ha sido mediante una cola de llamadas (valor queue-IDcolallamada) o una llamada a tu extensión (valor directcall). Únicamente para llamadas entrantes.

Notificación de registro

Ejemplo de contenido del índice 'register' de la variable POST cuando se envía una notificación a su URL de notificación de eventos de registro:

{
   "userexten": "8466271361103",
   "registered": "1",
   "IP": "185.8.245.123",
   "useragent": "Yealink SIP-T21P_E2 52.80.0.60",
   "datetime": "2020-10-30 22:33:56"
}

Los eventos de registro se enviará a la url "URL eventos de registro" mediante método POST con el índice "register" en formato "json".

La estructura de comunicación "json" será:

Clave Descripción
userexten Usuario SIP de la extensión que notifica el evento
registered Si el dispositivo está registrado, 1 está registrado, 0 no registrado
IP Dirección IP del dispositivo registrado
useragent Nombre del dispositivo registrado
expirationdate Fecha de expiración de registro del dispositivo registrado. La fecha se presentará en la zona horaria GMT, en formato YYYY-MM-DD HH:MM:SS

Notificación de grabación de llamadas

Ejemplo de contenido del índice 'callrecording' de la variable POST cuando se envía una notificación a su URL de notificación de eventos en llamadas:

{
   "uniqueid": "1576556033.1735",
   "src": "638829213",
   "dst": "34951504990",
   "userexten": "7491464423100",
   "status": "ANSWERED",
   "duration": "64",
   "file": "vPBX/callrecords/in/2022-11-15/2022_11_15_08_47_05_34951504990_638829213_1668498425.mp3",
   "URLAudio": "https://vdrive.netelip.com/index.php/apps/audioplayer/getaudiostream?file=vPBX/callrecords/in/2022-11-15/2022_11_15_08_47_05_34951504990_638829213_1668498425.mp3",
   "URLDownload": "https://vdrive.netelip.com/downloadAudioApivoice?file=Jc5AZoeuWBpYdQgBlZy9Zp62KuYDcpJF2PPUa3i2tvu3SI36izklk"
}

El evento de la grabación de llamadas se enviará a la url "URL eventos de llamada" mediante método POST con el índice "callrecording" en formato "json".

La estructura de comunicación "json" será:

Clave Descripción
uniqueid ID de llamada único
src Origen de la llamada
dst Destino de la llamada
userexten Usuario SIP de la extensión que notifica el evento
status Estado del evento. Valores: CHANUNAVAIL, BUSY, NOANSWER, ANSWERED, CANCEL, CONGESTION
duration Duración de la llamada en segundos
file Ubicación del fichero en vDrive
URLAudio URL en donde escuchar el fichero.
URLDownload URL de descarga del fichero.

Importante: La notificación de la grabación de llamadas es automática. Para tener activo el servicio es necesario tener la grabación de llamadas en vPBX, tenerla integradas con vDrive y activo en API Voice los eventos de llamadas.

Comandos disponibles

Esquema de un comando:

{
    "command": "nombrecomando",
    "options": "option1[;option2;option3]",
    "userfield": "customvalue"
}

Para controlar la realización y recepción de llamadas API Voice de netelip admite un conjunto de comandos amplio.

Cada comando está definido por 3 argumento y se entrega a API Voice en formato json.

Argumento Descripción
command Nombre de la orden o comando
options Valores separados por "," o ";" que modifican el comportamiento del comando
userfield Campo de uso libre para el usuario, se suele usar para indicar el estado o fase en el que se encuentra la llamada.

userfield es un valor definido por tu URL de control y que podrás aprovechar para indicarle en que momento de la ejecución se encuentra la llamada dentro del flujo de llamada planificado por ti.
Este campo no se procesa por API Voice y es devuelto exactamente igual en la siguiente petición.

answermachinedetect

Ejemplos de answermachinedetect:

{
    "command"  : "answermachinedetect",
    "options"  : "",
    "userfield": 2
}
{
    "command"  : "answermachinedetect",
    "options"  : "5.1,1.5,0.8,5,0.1,0.05,3,256",
    "userfield": 2
}

Intenta detectar un contestador automático basándose en los patrones de tiempo. Solo para llamadas salientes originadas desde el lanzador de llamadas.

Valores que contiene options

"options": "{initialSilence},{greeting},{afterGreetingSilence},{totalAnalysisTime},{minimumWordLength},{betweenWordsSilence},{maximumNumberOfWords},{silenceThreshold}",

ó

"options": "",

Valor Descripción Tipo Defecto
initialSilence Duración máxima en segundos de silencio antes del saludo. Si se excede se devuelve machine De 0 a 60 5.1
greeting Duración máxima en segundos del saludo. Si se excede se devuelve machine De 0 a 60 1.5
afterGreetingSilence Duración máxima de silencio en segundos tras detectar un saludo. Si se excede se devuelve machine De 0 a 60 0.8
totalAnalysisTime Tiempo máximo permitido en segundos para que el algoritmo decida si ha contestado un ser humano o un contestador automático De 0 a 60 5
minimumWordLength Duración mínima en segundos de la voz para ser considerada como una palabra De 0 a 60 0.1
betweenWordsSilence Duración mínima de silencio en segundos después de una palabra para considerar que el audio que le sigue es una palabra nueva De 0 a 60 0.05
maximumNumberOfWords Número máximo de palabras detectadas en el saludo. Si se excede se devuelve machine De 0 a 100 3
silenceThreshold Nivel medio de ruido que se considera como silencio De 0 a 256 256

Respuesta

La ejecución de “answermachinedetect” devolverá el estado de la detección de la contestación de la llamada dentro de la variable "statusanswermachinedetect".

Valor Descripción
machine Se detecta que la llamada fue contestada por un constestador automático
human Se detecta que la llamada fue contestada por un ser humano y no un contestador automático
notsure No se puede determinar si la llamada fue contestada por un ser humano o un contestador automático
hangup Se detecta un cuelge de la llamada

busy

Ejemplo de busy:

{
    "command"  : "busy",
    "options"  : "10",
    "userfield": "ocupado"
}

Dar señal de ocupado en la llamada actual.

Valores que contiene options

"options": "{seconds}",

Valor Descripción Tipo Defecto
seconds Duración en segundos de los tonos de ocupado antes de colgar De 0 a 30 30

callerid

Ejemplo de callerid:

{
    "command": "callerid",
    "options": "netelip;951223344",
    "userfield": "1"
}

Cambia el identificador llamada y se suele usar antes de realizar un desvío o transferencia. Por ejemplo antes de ejecutar un comando dial.

El nombre a mostrar es un texto breve que sólo será visible en la recepción de llamadas en aplicaciones o dispositivos de VoIP.

El número de teléfono a mostrar, será visible en la recepción de llamadas en aplicaciones o dispositivos de VoIP y en llamadas a números de teléfono de la red telefónica publica.

Valores que contiene options

"options": "{name};{phone}",

Valor Descripción Tipo Defecto
name Nombre a mostrar string
phone Número de teléfono a mostrar phone

conferenceroom

Ejemplo de conferenceroom:

{
    "command"  : "conferenceroom",
    "options"  : "",
    "userfield": "4"
}

Transfiere una llamada a su sala de conferencias de vPBX.

Valores que contiene options

El argumento options no se usa con el comando conferenceroom, se recomienda poner una cadena vacía o un valor 0.

congestion

Ejemplo de congestion:

{
    "command"  : "congestion",
    "options"  : "10",
    "userfield": "congestionado"
}

Dar señal de congestion en la red en la llamada actual.

Valores que contiene options

"options": "{seconds}",

Valor Descripción Tipo Defecto
seconds Duración en segundos de los tonos de congestion antes de colgar De 0 a 30 30

dial

Ejemplo de dial a una extensión:

{
    "command": "dial",
    "options": "extension,102,10,called,180",
    "userfield": "3"
}

Ejemplo dial a un número:

{
    "command": "dial",
    "options": "pstn,0034951223344,15,calling,180",
    "userfield": "3"
}

Ejemplo dial a un cuenta sip:

{
    "command": "dial",
    "options": "sipserver,103@pbx.midominio.com:5060,15,calling,180",
    "userfield": "3"
}

Ejemplo dial a un número con anuncio de locución de vPBX:

{
    "command": "dial",
    "options": "pstn,0034951223344,15,calling,180,local|bienvenido",
    "userfield": "3"
}

Ejemplo dial a un número con anuncio de audio remoto:

{
    "command": "dial",
    "options": "pstn,0034951223344,15,calling,180,remote|https://miservidor.com/ficheroaudio.mp3",
    "userfield": "3"
}

Hace una llamada a un destino, ya sea extensión de vPBX, teléfono de la red pública o extensión de un servidor SIP.

Puedes añadir varios destinos a la llamada concatenando cada número de teléfono o extensión por “&”.

Valores que contiene options

"options": "{type},{destination},{max_ring},{transfer},{timeout},{announce}",

Valor Descripción Tipo Defecto
type Destino de la llamada string
destination Extensión, número o cuenta sip de destino string
max_ring Duración máxima del ring en segundos integer
transfer Permiso de transferencia de llamadas string
timeout Tiempo máximo de duración de la llamada integer
announce Ubicación del fichero de audio a reproducir como anuncio al destino de la llamada string
musiconhold Categoría de la música en espera string

"type" puede tomar los valores "extension", "pstn" o "sipserver".

Se pueden añadir varios destionos a llamada concatenado cada número, extensión o cuenta sip con "&" en "destination".

"transfer" puede tomar los valores "calling" o "called".

"timeout" permite al usuario establecer la duración máxima de conversación en la llamada, siendo el valor mínimo de 5 segundos y máximo de 10 horas (36000 segundos).

"announce", ubicación del fichero de audio a reproducir como anuncio al destino de la llamada. Su sintaxis es "locatefileaudio|fileaudio", pudiendo ser

"musiconhold", nombre de la categoría de música en espera de vPBX.

Respuesta

La ejecución de “dial” devolverá el estado de la llamada dentro de la variable "description".

Valor Descripción
CHANUNAVAIL No existe destinatario de la llamada
BUSY El destinatario de la llamada da ocupado
NOANSWER El destinatario de la llamada no contesta la llamada
ANSWER El destinatario de la llamada contesta la llamada
CANCEL El llamante cuelga la llamada antes de que el destinatario la descuelgue
CONGESTION La llamada no se establece por problemas en la red telefónica.

google_voice2text

Ejemplo de google_voice2text:

{
    "command": "google_voice2text",
    "options": "AIzaSyBgfkU6CBytS1i9cbQKPX5zATwRQ2ml5Qo;es;15;0",
    "userfield": "3"
}

Se utiliza el servicio de reconocimiento de voz de Google para convertir la voz del llamante o llamado en texto legible por la aplicación del cliente.

Valores que contiene options

"options": "{key};{language};{wait};{beep};{rtimeout};{intkey}",

Valor Descripción Tipo Defecto
key Generada en la API de reconocimiento de voz de Google APIs. string
language Código del idioma a reconocer de la "Tabla de idiomas de reconocimiento de voz" string
wait Número de segundos de duración del silencio necesario para interrumpir la escucha y mandar la petición a Google integer
beep Reproducir el sonido "beep" para indicar el comienzo de la escucha 0 o 1
rtimeout Número de segundos de duración global de la escucha hasta mandar la petición a Google integer
intkey Tecla que al ser presionada interrumpirá la escucha de voz y será mandada la petición a Google integer #

"key" debe ser una Key de Google válida y para obtener una consulta el apartado para "Voice to Text".

"beep" solo tiene dos valores: 0 reproduce el sonido "Beep" y 1 no lo reproduce.

"rtimeout" Si el valor es establecido, el valor de la opción "wait" dejará de ser usado, de forma que solo se escuchará hasta los n segundos de voz establecidos y mandada la petición a Google.

"intkey" Si el valor es establecido y presionada la tecla durante la escucha de la voz, justo en ese momento será mandada la petición a Google. El valor por defecto es la "#".

Importante: En caso de tener establecido los valores para "rtimeout" y "intkey", la petición a Google se mandará en cuanto ocurra el primero de los dos casos, que llegue al final de los n segundos de escucha o se presione antes la tecla.

Respuesta

La ejecución de este comando devolverá dos valores:

google_voice2textSTR

Ejemplo de google_voice2textSTR (reconocimento solo por voz):

{
    "command": "google_voice2textSTR",
    "options": "palabrasofrase;es;local;audio",
    "userfield": "3"
}

Ejemplo de google_voice2textSTR (reconocimento por voz y marcación DTMF simultánea):

{
    "command": "google_voice2textSTR",
    "options": "palabrasofrase;es;local;audio;digitosadetectar;tiempodeespera",
    "userfield": "3"
}

Se utiliza el servicio de reconocimiento de voz de Google para convertir la voz del llamante o llamado en texto legible. A diferencia de "google_voice2text", el reconocimiento de voz es en tiempo real, no hay que esperar un determinado nº de segundos de silencio ni de escucha para convertir la voz en texto, sino que mientras se habla se va detectando la voz, de forma que si se detecta una palabra clave, detiene la conversión y devuelve el texto del audio detectado hasta ese momento.

Si al comando se le añade los parámetros de detección de DTMF (ndtmf, timeoutdtmf) será capaz de detectar voz y marcación DTMF simultáneamente.

Valores que contiene options

"options": "{keywords};{language};{locationfile};{fileaudio};{ndtmf};{timeoutdtmf}",

Valor Descripción Tipo
keywords Palabras o frases clave a detectar para finalizar la escucha y devolver el texto del audio. Una o más palabras/frases separados por coma ",". string
language Código del idioma a reconocer de la "Tabla de idiomas de reconocimiento de voz de Google" string
locationfile Localización del fichero a reproducir. "local", se reproducirá el fichero de audio localizado el panel de netelip, "remote", se reproducirá el fichero de una url "local" o "remote"
fileaudio Nombre de fichero de audio de locución de vPBX o url del audio remoto string
ndtmf Nº máximo de digitos a detectar integer
timeoutdtmf Tiempo de espera en segundos para marcar integer

Respuesta

La ejecución de este comando devolverá dos valores:

hangup

Ejemplo de hangup:

{
    "command"  : "hangup",
    "options"  : "",
    "userfield": "colgando"
}

Cuelga la llamada en curso.

Valores que contiene options

El argumento options no se usa con el comando hangup, se recomienda poner una cadena vacía o un valor 0.

ivr

Ejemplo de ivr:

{
    "command"  : "ivr",
    "options"  : "eligedepartamento",
    "userfield": 3
}

Transfiere una llamada a un IVR existente en vPBX.

Valores que contiene options

"options": "{name}",

Valor Descripción Tipo Defecto
name Nombre del ivr

language

Ejemplo de language:

{
    "command"  : "language",
    "options"  : "es",
    "userfield": 2
}

Establece el idioma para las locuciones predeterminadas cuando una llamada se desvía a vPBX.

Un ejemplo de locución puede ser "Por favor deje su mensaje después de la señal".

Por defecto el valor es el inglés (en).

Valores que contiene options

"options": "{language}",

Valor Descripción Valores Defecto
language Dos caracteres que indican el idioma de las locuciones "en" o "es" "en"

play

Ejemplos de play:

{
    "command"  : "play",
    "options"  : "local;musica1&musica2&musica3",
    "userfield": 4
}
{
    "command"  : "play",
    "options"  : "remote;http://www.midominio.com/mimusica.mp3",
    "userfield": "musica"
}

Reproduce un fichero de sonido guardado en vPBX.

La localización del fichero se indica con "local" o "remote", se usa ";" para separar la localización del nombre del fichero.

"local" indica un fichero ubicado en vPBX y "remote" indica una url accesible públicamente donde se encuentra el fichero de audio.

Se pueden reproducir varios ficheros de forma secuencial usando como separador entre ficheros "&" (solo disponible para localización "local").

Valores que contiene options

"options": "{location};{files}",

Valor Descripción Tipo Defecto
location Localización "local" o "remote"
files fichero o ficheros separados por "&" string

play_getdtmf

Ejemplos de play_getdtmf:

{
    "command"  : "play_getdtmf",
    "options"  : "local;musicadtmf;6000;3",
    "userfield": 2
}
{
    "command"  : "play_getdtmf",
    "options"  : "remote;http://www.midominio.com/mimusicadtmf.mp3;6000;2",
    "userfield": 2
}

Reproduce un fichero de sonido guardado en vPBX y espera a que sea marcada una opción DTMF.

La localización del fichero se indica con "local" o "remote", se usa ";" para separar la localización del nombre del fichero.

Una vez se pulse la cantidad máxima de dígitos DTMF parará la reproducción del fichero de audio y se enviara en la variable "dtmf" los dígitos marcados. En caso de no marcar ninguna tecla y pasado el tiempo de espera se enviará la variable "dtmf" con el valor “timeout”.

Valores que contiene options

"options": "{location};{files};{wait};{digits}",

Valor Descripción Tipo Defecto
location Localización "local" o "remote"
file nombre de fichero o url string
wait Tiempo de espera en milisegundos integer
digits Máximo de dígitos DTMF integer

queue

Ejemplo de queue:

{
    "command": "queue",
    "options": "soporte;3",
    "userfield": ""
}

Transfiere una llamada a una cola de llamadas existente en vPBX con o sin prioridad.

La prioridad tiene un valor entre 1 y 10 siendo 1 la mayor prioridad. El valor por defecto es 0 (sin prioridad). Cada llamada es encolada por orden de entrada (FIFO).

Valores que contiene options

"options": "{name};{priority}",

Valor Descripción Tipo Defecto
name Nombre de la cola
priority Valor de la prioridad De 0 a 10 0

record

Ejemplo de record:

{
    "command": "record",
    "options": "",
    "userfield": 1
}
{
    "command": "record",
    "options": "noconnect",
    "userfield": 1
}

Inicia la grabación de la llamada y finalizará cuando finalice la llamada.

La grabación de llamadas se realizará sobre el almacenamiento de netelip vDrive, con lo que será necesario activarlo antes de utilizar este comando (vDrive en su versión gratuita).

Una vez finalizada la llamada y realizada la grabación se devolverá la ruta del fichero en vDrive en la variable "description" con valor “/APIVoice/Record/fecha_llamada/nombre_fichero”, en la variable "URLAudio", la url del fichero para acceder a él sin necesidad de descargar y en la variable "URLDownload", la url del fichero para descargar.

Valores que contiene options

"options": {option},

Valor Descripción Tipo Defecto
option vacío o "noconnect" ""

Options puede estar vacío "" o tener el valor "noconnect". Cuando se activa "noconnect" la grabación comenzará en el mismo momento en el que se ejecute el comando. Por defecto cuando no se añade esta opción la grabación de la llamada comienza cuando se conecta con una extensión, número de teléfono o servidor.

send_dtmf

Ejemplo de send_dtmf:

{
    "command": "send_dtmf",
    "options": "123;0.25",
    "userfield": "1"
}

Genera tonos DTMF en la llamada en curso.

Valores que contiene options

"options": "{digits};{timeout}",

Valor Descripción Tipo Defecto
digits Lista de dítgitos, comprendidos entre 0-9,a-d,A-D,# y * string
timeout Duración en segundos entre tono y tono. Enter 1 y 60 float

speak

Ejemplos de speak:

{
    "command"  : "speak",
    "options"  : "netelip;Pedro;Bienvenido a netelip;1.2",
    "userfield": 2
}
{
    "command"  : "speak",
    "options"  : "google_TTS;es-ES-Standard-A;Bienvenido a netelip;1.2",
    "userfield": 2
}

Reproduce el texto con la voz que se especifica (Text to speech).

Los proveedores de TTS disponibles son "netelip" y "google_TTS".

Para ver el código de voz que usará el proveedor consultar el apartado con la tabla de códigos TTS.

Valores que contiene options

"options": "{provider};{code};{text};{speed}",

Valor Descripción Tipo Defecto
provider Proveedor: netelip o google_TTS
code Tabla de idiomas TTS. Consultar apartado.
text Texto a reproducir string
speed Velocidad de reproducción entre 1 y 2 float

speak_getdtmf

Ejemplos de speak_getdtmf:

{
    "command"  : "speak_getdtmf",
    "options"  : "netelip;Pedro;Introduzca su código de cliente;10000;5;1.2",
    "userfield": 2
}
{
    "command"  : "speak_getdtmf",
    "options"  : "google_TTS;es-ES-Standard-A;Introduzca su código de cliente;10000;5;1.2",
    "userfield": 2
}

Reproduce el texto con la voz que se especifica (Text to speech) y espera a que sea marcada una opción DTMF.

Los proveedores de TTS disponibles son "netelip" y "google_TTS".

Para ver el código de voz que usará el proveedor consultar el apartado con la tabla de códigos TTS.

Una vez se pulse la cantidad máxima de dígitos DTMF se enviara en la variable "dtmf" los dígitos marcados. En caso de no marcar ninguna tecla y pasado el tiempo de espera se enviará la variable "dtmf" con el valor “timeout”.

Valores que contiene options

"options": "{provider};{code};{text};{wait};{digits};{speed}",

Valor Descripción Tipo Defecto
provider Proveedor: netelip o google_TTS
code Tabla de idiomas TTS. Consultar apartado.
text Texto a reproducir string
wait Tiempo de espera en milisegundos integer
digits Máximo de dígitos DTMF integer
speed Velocidad de reproducción entre 1 y 2 float

voicemail

Ejemplos de voicemail:

{
    "command": "voicemail",
    "options": "100",
    "userfield": 9
}
{
    "command": "voicemail",
    "options": "110&112",
    "userfield": 11
}

Deja un mensaje en el buzón de voz de una o varias extensiones de vPBX. Si se añaden varias extensiones deben ir separadas por "&".

Valores que contiene options

"options": "{extensions}",

Valor Descripción Tipo Defecto
extensions Extensión o extensiones de vPBX separadas por "&" De 100 a 199

Errores

API Voice de netelip usa los siguientes códigos de error.

Estatos Descripción Cód. Respuesta
OK OK 200
ERROR Unauthorized 400
ERROR Command not found 401
ERROR Language not found 402
ERROR Invalid audio file 403
ERROR Invalid option/s 404
ERROR Options or userfield is empty 405
ERROR Userfield is empty 406
ERROR Invalid voicemail status 407
ERROR Voicemail do not exist 408
ERROR Extension/s do not exist 409
ERROR Invalid phone number 410
ERROR Queue do not exist 411
ERROR Conference room is not activated 412
ERROR vDrive service is not activated 413
ERROR netelip user do not exist or is not activated 414
ERROR Voice to text failed 415
ERROR Unable to get data recognition 416
ERROR Invalid send_dtmf options 417
ERROR Invalid SIP server port 418
ERROR Invalid SIP server IP address 419
ERROR File greater than 2MB 420
ERROR Invalid option timeout for dial command 422
ERROR Invalid option announce for dial command 423
ERROR Busy destination 424
ERROR Internal error server 500
ERROR Service Unavailable 503

Text to Speech (TTS)

API Voice de netelip dispone de dos proveedores para usar Text to Speech (TTS), netelip o Google_TTS.

netelip

Tabla de idiomas:

Proveedor Idioma Código Ejemplo options para speak
netelip Español masculino Pedro options: "netelip;Pedro;Bienvenido a netelip;1.2"
netelip Español femenino Silvia options: "netelip;Silvia;Bienvenido a netelip;1.2"
netelip Catalan masculino Jordi options: "netelip;Jordi;Bienvenido a netelip;1.2"
netelip Ingles masculino Brian options: "netelip;Brian;Bienvenido a netelip;1.2"

google_TTS

Tabla de idiomas:

Proveedor Idioma Código Género Ejemplo options para speak
google_TTS Afrikáans (Sudáfrica) af-ZA-Standard-A FEMENINO options: "google_TTS;af-ZA-Standard-A;Bienvenido a netelip;1.2"
google_TTS Árabe ar-XA-Standard-A FEMENINO options: "google_TTS;ar-XA-Standard-A;Bienvenido a netelip;1.2"
google_TTS Árabe ar-XA-Standard-B MASCULINO options: "google_TTS;ar-XA-Standard-B;Bienvenido a netelip;1.2"
google_TTS Árabe ar-XA-Standard-C MASCULINO options: "google_TTS;ar-XA-Standard-C;Bienvenido a netelip;1.2"
google_TTS Árabe ar-XA-Standard-D FEMENINO options: "google_TTS;ar-XA-Standard-D;Bienvenido a netelip;1.2"
google_TTS Árabe ar-XA-Wavenet-A FEMENINO options: "google_TTS;ar-XA-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Árabe ar-XA-Wavenet-B MASCULINO options: "google_TTS;ar-XA-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Árabe ar-XA-Wavenet-C MASCULINO options: "google_TTS;ar-XA-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Árabe ar-XA-Wavenet-D FEMENINO options: "google_TTS;ar-XA-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Bengalí (India) bn-IN-Standard-A FEMENINO options: "google_TTS;bn-IN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Bengalí (India) bn-IN-Standard-B MASCULINO options: "google_TTS;bn-IN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Bengalí (India) bn-IN-Wavenet-A FEMENINO options: "google_TTS;bn-IN-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Bengalí (India) bn-IN-Wavenet-B MASCULINO options: "google_TTS;bn-IN-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Búlgaro (Bulgaria) bg-bg-Standard-A FEMENINO options: "google_TTS;bg-bg-Standard-A;Bienvenido a netelip;1.2"
google_TTS Catalán (España) ca-es-Standard-A FEMENINO options: "google_TTS;ca-es-Standard-A;Bienvenido a netelip;1.2"
google_TTS Chino (Hong Kong) yue-HK-Standard-A FEMENINO options: "google_TTS;yue-HK-Standard-A;Bienvenido a netelip;1.2"
google_TTS Chino (Hong Kong) yue-HK-Standard-B MASCULINO options: "google_TTS;yue-HK-Standard-B;Bienvenido a netelip;1.2"
google_TTS Chino (Hong Kong) yue-HK-Standard-C FEMENINO options: "google_TTS;yue-HK-Standard-C;Bienvenido a netelip;1.2"
google_TTS Chino (Hong Kong) yue-HK-Standard-D MASCULINO options: "google_TTS;yue-HK-Standard-D;Bienvenido a netelip;1.2"
google_TTS Checo (República Checa) cs-CZ-Standard-A FEMENINO options: "google_TTS;cs-CZ-Standard-A;Bienvenido a netelip;1.2"
google_TTS Checo (República Checa) cs-CZ-Wavenet-A FEMENINO options: "google_TTS;cs-CZ-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Danés (Dinamarca) da-DK-Standard-A FEMENINO options: "google_TTS;da-DK-Standard-A;Bienvenido a netelip;1.2"
google_TTS Danés (Dinamarca) da-DK-Standard-C MASCULINO options: "google_TTS;da-DK-Standard-C;Bienvenido a netelip;1.2"
google_TTS Danés (Dinamarca) da-DK-Standard-D FEMENINO options: "google_TTS;da-DK-Standard-D;Bienvenido a netelip;1.2"
google_TTS Danés (Dinamarca) da-DK-Standard-E FEMENINO options: "google_TTS;da-DK-Standard-E;Bienvenido a netelip;1.2"
google_TTS Danés (Dinamarca) da-DK-Wavenet-A FEMENINO options: "google_TTS;da-DK-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Danés (Dinamarca) da-DK-Wavenet-C MASCULINO options: "google_TTS;da-DK-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Danés (Dinamarca) da-DK-Wavenet-D FEMENINO options: "google_TTS;da-DK-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Danés (Dinamarca) da-DK-Wavenet-E FEMENINO options: "google_TTS;da-DK-Wavenet-E;Bienvenido a netelip;1.2"
google_TTS Holandés (Bélgica) nl-BE-Standard-A FEMENINO options: "google_TTS;nl-BE-Standard-A;Bienvenido a netelip;1.2"
google_TTS Holandés (Bélgica) nl-BE-Standard-B MASCULINO options: "google_TTS;nl-BE-Standard-B;Bienvenido a netelip;1.2"
google_TTS Holandés (Bélgica) nl-BE-Wavenet-A FEMENINO options: "google_TTS;nl-BE-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Holandés (Bélgica) nl-BE-Wavenet-B MASCULINO options: "google_TTS;nl-BE-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Holandés (Países Bajos) nl-NL-Standard-A FEMENINO options: "google_TTS;nl-NL-Standard-A;Bienvenido a netelip;1.2"
google_TTS Holandés (Países Bajos) nl-NL-Standard-B MASCULINO options: "google_TTS;nl-NL-Standard-B;Bienvenido a netelip;1.2"
google_TTS Holandés (Países Bajos) nl-NL-Standard-C MASCULINO options: "google_TTS;nl-NL-Standard-C;Bienvenido a netelip;1.2"
google_TTS Holandés (Países Bajos) nl-NL-Standard-D FEMENINO options: "google_TTS;nl-NL-Standard-D;Bienvenido a netelip;1.2"
google_TTS Holandés (Países Bajos) nl-NL-Standard-E FEMENINO options: "google_TTS;nl-NL-Standard-E;Bienvenido a netelip;1.2"
google_TTS Holandés (Países Bajos) nl-NL-Wavenet-A FEMENINO options: "google_TTS;nl-NL-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Holandés (Países Bajos) nl-NL-Wavenet-B MASCULINO options: "google_TTS;nl-NL-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Holandés (Países Bajos) nl-NL-Wavenet-C MASCULINO options: "google_TTS;nl-NL-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Holandés (Países Bajos) nl-NL-Wavenet-D FEMENINO options: "google_TTS;nl-NL-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Holandés (Países Bajos) nl-NL-Wavenet-E FEMENINO options: "google_TTS;nl-NL-Wavenet-E;Bienvenido a netelip;1.2"
google_TTS Inglés (Australia) en-AU-Standard-A FEMENINO options: "google_TTS;en-AU-Standard-A;Bienvenido a netelip;1.2"
google_TTS Inglés (Australia) en-AU-Standard-B MASCULINO options: "google_TTS;en-AU-Standard-B;Bienvenido a netelip;1.2"
google_TTS Inglés (Australia) en-AU-Standard-C FEMENINO options: "google_TTS;en-AU-Standard-C;Bienvenido a netelip;1.2"
google_TTS Inglés (Australia) en-AU-Standard-D MASCULINO options: "google_TTS;en-AU-Standard-D;Bienvenido a netelip;1.2"
google_TTS Inglés (Australia) en-AU-Wavenet-A FEMENINO options: "google_TTS;en-AU-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Inglés (Australia) en-AU-Wavenet-B MASCULINO options: "google_TTS;en-AU-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Inglés (Australia) en-AU-Wavenet-C FEMENINO options: "google_TTS;en-AU-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Inglés (Australia) en-AU-Wavenet-D MASCULINO options: "google_TTS;en-AU-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Inglés (India) en-IN-Standard-A FEMENINO options: "google_TTS;en-IN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Inglés (India) en-IN-Standard-B MASCULINO options: "google_TTS;en-IN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Inglés (India) en-IN-Standard-C MASCULINO options: "google_TTS;en-IN-Standard-C;Bienvenido a netelip;1.2"
google_TTS Inglés (India) en-IN-Standard-D FEMENINO options: "google_TTS;en-IN-Standard-D;Bienvenido a netelip;1.2"
google_TTS Inglés (India) en-IN-Wavenet-A FEMENINO options: "google_TTS;en-IN-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Inglés (India) en-IN-Wavenet-B MASCULINO options: "google_TTS;en-IN-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Inglés (India) en-IN-Wavenet-C MASCULINO options: "google_TTS;en-IN-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Inglés (India) en-IN-Wavenet-D FEMENINO options: "google_TTS;en-IN-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Inglés (Reino Unido) en-GB-Standard-A FEMENINO options: "google_TTS;en-GB-Standard-A;Bienvenido a netelip;1.2"
google_TTS Inglés (Reino Unido) en-GB-Standard-B MASCULINO options: "google_TTS;en-GB-Standard-B;Bienvenido a netelip;1.2"
google_TTS Inglés (Reino Unido) en-GB-Standard-C FEMENINO options: "google_TTS;en-GB-Standard-C;Bienvenido a netelip;1.2"
google_TTS Inglés (Reino Unido) en-GB-Standard-D MASCULINO options: "google_TTS;en-GB-Standard-D;Bienvenido a netelip;1.2"
google_TTS Inglés (Reino Unido) en-GB-Standard-F FEMENINO options: "google_TTS;en-GB-Standard-F;Bienvenido a netelip;1.2"
google_TTS Inglés (Reino Unido) en-GB-Wavenet-A FEMENINO options: "google_TTS;en-GB-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Inglés (Reino Unido) en-GB-Wavenet-B MASCULINO options: "google_TTS;en-GB-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Inglés (Reino Unido) en-GB-Wavenet-C FEMENINO options: "google_TTS;en-GB-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Inglés (Reino Unido) en-GB-Wavenet-D MASCULINO options: "google_TTS;en-GB-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Inglés (Reino Unido) en-GB-Wavenet-F FEMENINO options: "google_TTS;en-GB-Wavenet-F;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Standard-A MASCULINO options: "google_TTS;en-US-Standard-A;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Standard-B MASCULINO options: "google_TTS;en-US-Standard-B;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Standard-C FEMENINO options: "google_TTS;en-US-Standard-C;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Standard-D MASCULINO options: "google_TTS;en-US-Standard-D;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Standard-E FEMENINO options: "google_TTS;en-US-Standard-E;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Standard-F FEMENINO options: "google_TTS;en-US-Standard-F;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Standard-G FEMENINO options: "google_TTS;en-US-Standard-G;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Standard-H FEMENINO options: "google_TTS;en-US-Standard-H;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Standard-I MASCULINO options: "google_TTS;en-US-Standard-I;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Standard-J MASCULINO options: "google_TTS;en-US-Standard-J;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Wavenet-A MASCULINO options: "google_TTS;en-US-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Wavenet-B MASCULINO options: "google_TTS;en-US-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Wavenet-C FEMENINO options: "google_TTS;en-US-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Wavenet-D MASCULINO options: "google_TTS;en-US-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Wavenet-E FEMENINO options: "google_TTS;en-US-Wavenet-E;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Wavenet-F FEMENINO options: "google_TTS;en-US-Wavenet-F;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Wavenet-G FEMENINO options: "google_TTS;en-US-Wavenet-G;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Wavenet-H FEMENINO options: "google_TTS;en-US-Wavenet-H;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Wavenet-I MASCULINO options: "google_TTS;en-US-Wavenet-I;Bienvenido a netelip;1.2"
google_TTS Inglés (EE.UU.) en-US-Wavenet-J MASCULINO options: "google_TTS;en-US-Wavenet-J;Bienvenido a netelip;1.2"
google_TTS Filipino (Filipinas) fil-PH-Standard-A FEMENINO options: "google_TTS;fil-PH-Standard-A;Bienvenido a netelip;1.2"
google_TTS Filipino (Filipinas) fil-PH-Standard-B FEMENINO options: "google_TTS;fil-PH-Standard-B;Bienvenido a netelip;1.2"
google_TTS Filipino (Filipinas) fil-PH-Standard-C MASCULINO options: "google_TTS;fil-PH-Standard-C;Bienvenido a netelip;1.2"
google_TTS Filipino (Filipinas) fil-PH-Standard-D MASCULINO options: "google_TTS;fil-PH-Standard-D;Bienvenido a netelip;1.2"
google_TTS Filipino (Filipinas) fil-PH-Wavenet-A FEMENINO options: "google_TTS;fil-PH-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Filipino (Filipinas) fil-PH-Wavenet-B FEMENINO options: "google_TTS;fil-PH-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Filipino (Filipinas) fil-PH-Wavenet-C MASCULINO options: "google_TTS;fil-PH-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Filipino (Filipinas) fil-PH-Wavenet-D MASCULINO options: "google_TTS;fil-PH-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Finés (Finlandia) fi-FI-Standard-A FEMENINO options: "google_TTS;fi-FI-Standard-A;Bienvenido a netelip;1.2"
google_TTS Finés (Finlandia) fi-FI-Wavenet-A FEMENINO options: "google_TTS;fi-FI-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Francés (Canadá) fr-CA-Standard-A FEMENINO options: "google_TTS;fr-CA-Standard-A;Bienvenido a netelip;1.2"
google_TTS Francés (Canadá) fr-CA-Standard-B MASCULINO options: "google_TTS;fr-CA-Standard-B;Bienvenido a netelip;1.2"
google_TTS Francés (Canadá) fr-CA-Standard-C FEMENINO options: "google_TTS;fr-CA-Standard-C;Bienvenido a netelip;1.2"
google_TTS Francés (Canadá) fr-CA-Standard-D MASCULINO options: "google_TTS;fr-CA-Standard-D;Bienvenido a netelip;1.2"
google_TTS Francés (Canadá) fr-CA-Wavenet-A FEMENINO options: "google_TTS;fr-CA-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Francés (Canadá) fr-CA-Wavenet-B MASCULINO options: "google_TTS;fr-CA-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Francés (Canadá) fr-CA-Wavenet-C FEMENINO options: "google_TTS;fr-CA-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Francés (Canadá) fr-CA-Wavenet-D MASCULINO options: "google_TTS;fr-CA-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Francés (Francia) fr-FR-Standard-A FEMENINO options: "google_TTS;fr-FR-Standard-A;Bienvenido a netelip;1.2"
google_TTS Francés (Francia) fr-FR-Standard-B MASCULINO options: "google_TTS;fr-FR-Standard-B;Bienvenido a netelip;1.2"
google_TTS Francés (Francia) fr-FR-Standard-C FEMENINO options: "google_TTS;fr-FR-Standard-C;Bienvenido a netelip;1.2"
google_TTS Francés (Francia) fr-FR-Standard-D MASCULINO options: "google_TTS;fr-FR-Standard-D;Bienvenido a netelip;1.2"
google_TTS Francés (Francia) fr-FR-Standard-E FEMENINO options: "google_TTS;fr-FR-Standard-E;Bienvenido a netelip;1.2"
google_TTS Francés (Francia) fr-FR-Wavenet-A FEMENINO options: "google_TTS;fr-FR-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Francés (Francia) fr-FR-Wavenet-B MASCULINO options: "google_TTS;fr-FR-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Francés (Francia) fr-FR-Wavenet-C FEMENINO options: "google_TTS;fr-FR-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Francés (Francia) fr-FR-Wavenet-D MASCULINO options: "google_TTS;fr-FR-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Francés (Francia) fr-FR-Wavenet-E FEMENINO options: "google_TTS;fr-FR-Wavenet-E;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Standard-A FEMENINO options: "google_TTS;de-DE-Standard-A;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Standard-B MASCULINO options: "google_TTS;de-DE-Standard-B;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Standard-C FEMENINO options: "google_TTS;de-DE-Standard-C;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Standard-D MASCULINO options: "google_TTS;de-DE-Standard-D;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Standard-E MASCULINO options: "google_TTS;de-DE-Standard-E;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Standard-F FEMENINO options: "google_TTS;de-DE-Standard-F;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Wavenet-A FEMENINO options: "google_TTS;de-DE-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Wavenet-B MASCULINO options: "google_TTS;de-DE-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Wavenet-C FEMENINO options: "google_TTS;de-DE-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Wavenet-D MASCULINO options: "google_TTS;de-DE-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Wavenet-E MASCULINO options: "google_TTS;de-DE-Wavenet-E;Bienvenido a netelip;1.2"
google_TTS Alemán (Alemania) de-DE-Wavenet-F FEMENINO options: "google_TTS;de-DE-Wavenet-F;Bienvenido a netelip;1.2"
google_TTS Griego (Grecia) el-GR-Standard-A FEMENINO options: "google_TTS;el-GR-Standard-A;Bienvenido a netelip;1.2"
google_TTS Griego (Grecia) el-GR-Wavenet-A FEMENINO options: "google_TTS;el-GR-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Guyaratí (India) gu-IN-Standard-A FEMENINO options: "google_TTS;gu-IN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Guyaratí (India) gu-IN-Standard-B MASCULINO options: "google_TTS;gu-IN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Guyaratí (India) gu-IN-Wavenet-A FEMENINO options: "google_TTS;gu-IN-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Guyaratí (India) gu-IN-Wavenet-B MASCULINO options: "google_TTS;gu-IN-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Hindi (India) hi-IN-Standard-A FEMENINO options: "google_TTS;hi-IN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Hindi (India) hi-IN-Standard-B MASCULINO options: "google_TTS;hi-IN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Hindi (India) hi-IN-Standard-C MASCULINO options: "google_TTS;hi-IN-Standard-C;Bienvenido a netelip;1.2"
google_TTS Hindi (India) hi-IN-Standard-D FEMENINO options: "google_TTS;hi-IN-Standard-D;Bienvenido a netelip;1.2"
google_TTS Hindi (India) hi-IN-Wavenet-A FEMENINO options: "google_TTS;hi-IN-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Hindi (India) hi-IN-Wavenet-B MASCULINO options: "google_TTS;hi-IN-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Hindi (India) hi-IN-Wavenet-C MASCULINO options: "google_TTS;hi-IN-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Hindi (India) hi-IN-Wavenet-D FEMENINO options: "google_TTS;hi-IN-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Húngaro (Hungría) hu-HU-Standard-A FEMENINO options: "google_TTS;hu-HU-Standard-A;Bienvenido a netelip;1.2"
google_TTS Húngaro (Hungría) hu-HU-Wavenet-A FEMENINO options: "google_TTS;hu-HU-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Islandés (Islandia) is-is-Standard-A FEMENINO options: "google_TTS;is-is-Standard-A;Bienvenido a netelip;1.2"
google_TTS Indonesio (Indonesia) id-ID-Standard-A FEMENINO options: "google_TTS;id-ID-Standard-A;Bienvenido a netelip;1.2"
google_TTS Indonesio (Indonesia) id-ID-Standard-B MASCULINO options: "google_TTS;id-ID-Standard-B;Bienvenido a netelip;1.2"
google_TTS Indonesio (Indonesia) id-ID-Standard-C MASCULINO options: "google_TTS;id-ID-Standard-C;Bienvenido a netelip;1.2"
google_TTS Indonesio (Indonesia) id-ID-Standard-D FEMENINO options: "google_TTS;id-ID-Standard-D;Bienvenido a netelip;1.2"
google_TTS Indonesio (Indonesia) id-ID-Wavenet-A FEMENINO options: "google_TTS;id-ID-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Indonesio (Indonesia) id-ID-Wavenet-B MASCULINO options: "google_TTS;id-ID-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Indonesio (Indonesia) id-ID-Wavenet-C MASCULINO options: "google_TTS;id-ID-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Indonesio (Indonesia) id-ID-Wavenet-D FEMENINO options: "google_TTS;id-ID-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Italiano (Italia) it-IT-Standard-A FEMENINO options: "google_TTS;it-IT-Standard-A;Bienvenido a netelip;1.2"
google_TTS Italiano (Italia) it-IT-Standard-B FEMENINO options: "google_TTS;it-IT-Standard-B;Bienvenido a netelip;1.2"
google_TTS Italiano (Italia) it-IT-Standard-C MASCULINO options: "google_TTS;it-IT-Standard-C;Bienvenido a netelip;1.2"
google_TTS Italiano (Italia) it-IT-Standard-D MASCULINO options: "google_TTS;it-IT-Standard-D;Bienvenido a netelip;1.2"
google_TTS Italiano (Italia) it-IT-Wavenet-A FEMENINO options: "google_TTS;it-IT-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Italiano (Italia) it-IT-Wavenet-B FEMENINO options: "google_TTS;it-IT-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Italiano (Italia) it-IT-Wavenet-C MASCULINO options: "google_TTS;it-IT-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Italiano (Italia) it-IT-Wavenet-D MASCULINO options: "google_TTS;it-IT-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Japonés (Japón) ja-JP-Standard-A FEMENINO options: "google_TTS;ja-JP-Standard-A;Bienvenido a netelip;1.2"
google_TTS Japonés (Japón) ja-JP-Standard-B FEMENINO options: "google_TTS;ja-JP-Standard-B;Bienvenido a netelip;1.2"
google_TTS Japonés (Japón) ja-JP-Standard-C MASCULINO options: "google_TTS;ja-JP-Standard-C;Bienvenido a netelip;1.2"
google_TTS Japonés (Japón) ja-JP-Standard-D MASCULINO options: "google_TTS;ja-JP-Standard-D;Bienvenido a netelip;1.2"
google_TTS Japonés (Japón) ja-JP-Wavenet-A FEMENINO options: "google_TTS;ja-JP-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Japonés (Japón) ja-JP-Wavenet-B FEMENINO options: "google_TTS;ja-JP-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Japonés (Japón) ja-JP-Wavenet-C MASCULINO options: "google_TTS;ja-JP-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Japonés (Japón) ja-JP-Wavenet-D MASCULINO options: "google_TTS;ja-JP-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Canarés (India) kn-IN-Standard-A FEMENINO options: "google_TTS;kn-IN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Canarés (India) kn-IN-Standard-B MASCULINO options: "google_TTS;kn-IN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Canarés (India) kn-IN-Wavenet-A FEMENINO options: "google_TTS;kn-IN-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Canarés (India) kn-IN-Wavenet-B MASCULINO options: "google_TTS;kn-IN-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Coreano (Corea del Sur) ko-KR-Standard-A FEMENINO options: "google_TTS;ko-KR-Standard-A;Bienvenido a netelip;1.2"
google_TTS Coreano (Corea del Sur) ko-KR-Standard-B FEMENINO options: "google_TTS;ko-KR-Standard-B;Bienvenido a netelip;1.2"
google_TTS Coreano (Corea del Sur) ko-KR-Standard-C MASCULINO options: "google_TTS;ko-KR-Standard-C;Bienvenido a netelip;1.2"
google_TTS Coreano (Corea del Sur) ko-KR-Standard-D MASCULINO options: "google_TTS;ko-KR-Standard-D;Bienvenido a netelip;1.2"
google_TTS Coreano (Corea del Sur) ko-KR-Wavenet-A FEMENINO options: "google_TTS;ko-KR-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Coreano (Corea del Sur) ko-KR-Wavenet-B FEMENINO options: "google_TTS;ko-KR-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Coreano (Corea del Sur) ko-KR-Wavenet-C MASCULINO options: "google_TTS;ko-KR-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Coreano (Corea del Sur) ko-KR-Wavenet-D MASCULINO options: "google_TTS;ko-KR-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Letón (Letonia) lv-lv-Standard-A MASCULINO options: "google_TTS;lv-lv-Standard-A;Bienvenido a netelip;1.2"
google_TTS Malayo (Malasia) ms-MY-Standard-A FEMENINO options: "google_TTS;ms-MY-Standard-A;Bienvenido a netelip;1.2"
google_TTS Malayo (Malasia) ms-MY-Standard-B MASCULINO options: "google_TTS;ms-MY-Standard-B;Bienvenido a netelip;1.2"
google_TTS Malayo (Malasia) ms-MY-Standard-C FEMENINO options: "google_TTS;ms-MY-Standard-C;Bienvenido a netelip;1.2"
google_TTS Malayo (Malasia) ms-MY-Standard-D MASCULINO options: "google_TTS;ms-MY-Standard-D;Bienvenido a netelip;1.2"
google_TTS Malayo (Malasia) ms-MY-Wavenet-A FEMENINO options: "google_TTS;ms-MY-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Malayo (Malasia) ms-MY-Wavenet-B MASCULINO options: "google_TTS;ms-MY-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Malayo (Malasia) ms-MY-Wavenet-C FEMENINO options: "google_TTS;ms-MY-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Malayo (Malasia) ms-MY-Wavenet-D MASCULINO options: "google_TTS;ms-MY-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Malabar (India) ml-IN-Standard-A FEMENINO options: "google_TTS;ml-IN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Malabar (India) ml-IN-Standard-B MASCULINO options: "google_TTS;ml-IN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Malabar (India) ml-IN-Wavenet-A FEMENINO options: "google_TTS;ml-IN-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Malabar (India) ml-IN-Wavenet-B MASCULINO options: "google_TTS;ml-IN-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-CN-Standard-A FEMENINO options: "google_TTS;cmn-CN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-CN-Standard-B MASCULINO options: "google_TTS;cmn-CN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-CN-Standard-C MASCULINO options: "google_TTS;cmn-CN-Standard-C;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-CN-Standard-D FEMENINO options: "google_TTS;cmn-CN-Standard-D;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-CN-Wavenet-A FEMENINO options: "google_TTS;cmn-CN-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-CN-Wavenet-B MASCULINO options: "google_TTS;cmn-CN-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-CN-Wavenet-C MASCULINO options: "google_TTS;cmn-CN-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-CN-Wavenet-D FEMENINO options: "google_TTS;cmn-CN-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-TW-Standard-A FEMENINO options: "google_TTS;cmn-TW-Standard-A;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-TW-Standard-B MASCULINO options: "google_TTS;cmn-TW-Standard-B;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-TW-Standard-C MASCULINO options: "google_TTS;cmn-TW-Standard-C;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-TW-Wavenet-A FEMENINO options: "google_TTS;cmn-TW-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-TW-Wavenet-B MASCULINO options: "google_TTS;cmn-TW-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Chino mandarín cmn-TW-Wavenet-C MASCULINO options: "google_TTS;cmn-TW-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-NO-Standard-A FEMENINO options: "google_TTS;nb-NO-Standard-A;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-NO-Standard-B MASCULINO options: "google_TTS;nb-NO-Standard-B;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-NO-Standard-C FEMENINO options: "google_TTS;nb-NO-Standard-C;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-NO-Standard-D MASCULINO options: "google_TTS;nb-NO-Standard-D;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-NO-Wavenet-A FEMENINO options: "google_TTS;nb-NO-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-NO-Wavenet-B MASCULINO options: "google_TTS;nb-NO-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-NO-Wavenet-C FEMENINO options: "google_TTS;nb-NO-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-NO-Wavenet-D MASCULINO options: "google_TTS;nb-NO-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-no-Standard-E FEMENINO options: "google_TTS;nb-no-Standard-E;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-no-Standard-E FEMENINO options: "google_TTS;nb-no-Standard-E;Bienvenido a netelip;1.2"
google_TTS Noruego (Noruega) nb-no-Wavenet-E FEMENINO options: "google_TTS;nb-no-Wavenet-E;Bienvenido a netelip;1.2"
google_TTS Polaco (Polonia) pl-PL-Standard-A FEMENINO options: "google_TTS;pl-PL-Standard-A;Bienvenido a netelip;1.2"
google_TTS Polaco (Polonia) pl-PL-Standard-B MASCULINO options: "google_TTS;pl-PL-Standard-B;Bienvenido a netelip;1.2"
google_TTS Polaco (Polonia) pl-PL-Standard-C MASCULINO options: "google_TTS;pl-PL-Standard-C;Bienvenido a netelip;1.2"
google_TTS Polaco (Polonia) pl-PL-Standard-D FEMENINO options: "google_TTS;pl-PL-Standard-D;Bienvenido a netelip;1.2"
google_TTS Polaco (Polonia) pl-PL-Standard-E FEMENINO options: "google_TTS;pl-PL-Standard-E;Bienvenido a netelip;1.2"
google_TTS Polaco (Polonia) pl-PL-Wavenet-A FEMENINO options: "google_TTS;pl-PL-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Polaco (Polonia) pl-PL-Wavenet-B MASCULINO options: "google_TTS;pl-PL-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Polaco (Polonia) pl-PL-Wavenet-C MASCULINO options: "google_TTS;pl-PL-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Polaco (Polonia) pl-PL-Wavenet-D FEMENINO options: "google_TTS;pl-PL-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Polaco (Polonia) pl-PL-Wavenet-E FEMENINO options: "google_TTS;pl-PL-Wavenet-E;Bienvenido a netelip;1.2"
google_TTS Portugués (Brasil) pt-BR-Standard-A FEMENINO options: "google_TTS;pt-BR-Standard-A;Bienvenido a netelip;1.2"
google_TTS Portugués (Brasil) pt-BR-Standard-B MASCULINO options: "google_TTS;pt-BR-Standard-B;Bienvenido a netelip;1.2"
google_TTS Portugués (Brasil) pt-BR-Wavenet-A FEMENINO options: "google_TTS;pt-BR-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Portugués (Brasil) pt-BR-Wavenet-B MASCULINO options: "google_TTS;pt-BR-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Portugués (Portugal) pt-PT-Standard-A FEMENINO options: "google_TTS;pt-PT-Standard-A;Bienvenido a netelip;1.2"
google_TTS Portugués (Portugal) pt-PT-Standard-B MASCULINO options: "google_TTS;pt-PT-Standard-B;Bienvenido a netelip;1.2"
google_TTS Portugués (Portugal) pt-PT-Standard-C MASCULINO options: "google_TTS;pt-PT-Standard-C;Bienvenido a netelip;1.2"
google_TTS Portugués (Portugal) pt-PT-Standard-D FEMENINO options: "google_TTS;pt-PT-Standard-D;Bienvenido a netelip;1.2"
google_TTS Portugués (Portugal) pt-PT-Wavenet-A FEMENINO options: "google_TTS;pt-PT-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Portugués (Portugal) pt-PT-Wavenet-B MASCULINO options: "google_TTS;pt-PT-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Portugués (Portugal) pt-PT-Wavenet-C MASCULINO options: "google_TTS;pt-PT-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Portugués (Portugal) pt-PT-Wavenet-D FEMENINO options: "google_TTS;pt-PT-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Panyabí (India) pa-IN-Standard-A FEMENINO options: "google_TTS;pa-IN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Panyabí (India) pa-IN-Standard-B MASCULINO options: "google_TTS;pa-IN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Panyabí (India) pa-IN-Standard-C FEMENINO options: "google_TTS;pa-IN-Standard-C;Bienvenido a netelip;1.2"
google_TTS Panyabí (India) pa-IN-Standard-D MASCULINO options: "google_TTS;pa-IN-Standard-D;Bienvenido a netelip;1.2"
google_TTS Panyabí (India) pa-IN-Wavenet-A FEMENINO options: "google_TTS;pa-IN-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Panyabí (India) pa-IN-Wavenet-B MASCULINO options: "google_TTS;pa-IN-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Panyabí (India) pa-IN-Wavenet-C FEMENINO options: "google_TTS;pa-IN-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Panyabí (India) pa-IN-Wavenet-D MASCULINO options: "google_TTS;pa-IN-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Rumano (Rumania) ro-RO-Standard-A FEMENINO options: "google_TTS;ro-RO-Standard-A;Bienvenido a netelip;1.2"
google_TTS Rumano (Rumania) ro-RO-Wavenet-A FEMENINO options: "google_TTS;ro-RO-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Ruso (Rusia) ru-RU-Standard-A FEMENINO options: "google_TTS;ru-RU-Standard-A;Bienvenido a netelip;1.2"
google_TTS Ruso (Rusia) ru-RU-Standard-B MASCULINO options: "google_TTS;ru-RU-Standard-B;Bienvenido a netelip;1.2"
google_TTS Ruso (Rusia) ru-RU-Standard-C FEMENINO options: "google_TTS;ru-RU-Standard-C;Bienvenido a netelip;1.2"
google_TTS Ruso (Rusia) ru-RU-Standard-D MASCULINO options: "google_TTS;ru-RU-Standard-D;Bienvenido a netelip;1.2"
google_TTS Ruso (Rusia) ru-RU-Standard-E FEMENINO options: "google_TTS;ru-RU-Standard-E;Bienvenido a netelip;1.2"
google_TTS Ruso (Rusia) ru-RU-Wavenet-A FEMENINO options: "google_TTS;ru-RU-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Ruso (Rusia) ru-RU-Wavenet-B MASCULINO options: "google_TTS;ru-RU-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Ruso (Rusia) ru-RU-Wavenet-C FEMENINO options: "google_TTS;ru-RU-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Ruso (Rusia) ru-RU-Wavenet-D MASCULINO options: "google_TTS;ru-RU-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Ruso (Rusia) ru-RU-Wavenet-E FEMENINO options: "google_TTS;ru-RU-Wavenet-E;Bienvenido a netelip;1.2"
google_TTS Serbio (cirílico) sr-rs-Standard-A FEMENINO options: "google_TTS;sr-rs-Standard-A;Bienvenido a netelip;1.2"
google_TTS Eslovaco (Eslovaquia) sk-SK-Standard-A FEMENINO options: "google_TTS;sk-SK-Standard-A;Bienvenido a netelip;1.2"
google_TTS Eslovaco (Eslovaquia) sk-SK-Wavenet-A FEMENINO options: "google_TTS;sk-SK-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Español (España) es-ES-Standard-A FEMENINO options: "google_TTS;es-ES-Standard-A;Bienvenido a netelip;1.2"
google_TTS Español (España) es-ES-Standard-B MASCULINO options: "google_TTS;es-ES-Standard-B;Bienvenido a netelip;1.2"
google_TTS Español (España) es-ES-Standard-C FEMENINO options: "google_TTS;es-ES-Standard-C;Bienvenido a netelip;1.2"
google_TTS Español (España) es-ES-Standard-D FEMENINO options: "google_TTS;es-ES-Standard-D;Bienvenido a netelip;1.2"
google_TTS Español (España) es-ES-Wavenet-B MASCULINO options: "google_TTS;es-ES-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Español (España) es-ES-Wavenet-C FEMENINO options: "google_TTS;es-ES-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Español (España) es-ES-Wavenet-D FEMENINO options: "google_TTS;es-ES-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Español (EE.UU.) es-US-Standard-A FEMENINO options: "google_TTS;es-US-Standard-A;Bienvenido a netelip;1.2"
google_TTS Español (EE.UU.) es-US-Standard-B MASCULINO options: "google_TTS;es-US-Standard-B;Bienvenido a netelip;1.2"
google_TTS Español (EE.UU.) es-US-Standard-C MASCULINO options: "google_TTS;es-US-Standard-C;Bienvenido a netelip;1.2"
google_TTS Español (EE.UU.) es-US-Wavenet-A FEMENINO options: "google_TTS;es-US-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Español (EE.UU.) es-US-Wavenet-B MASCULINO options: "google_TTS;es-US-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Español (EE.UU.) es-US-Wavenet-C MASCULINO options: "google_TTS;es-US-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Sueco (Suecia) sv-SE-Standard-A FEMENINO options: "google_TTS;sv-SE-Standard-A;Bienvenido a netelip;1.2"
google_TTS Sueco (Suecia) sv-SE-Standard-B FEMENINO options: "google_TTS;sv-SE-Standard-B;Bienvenido a netelip;1.2"
google_TTS Sueco (Suecia) sv-SE-Standard-C FEMENINO options: "google_TTS;sv-SE-Standard-C;Bienvenido a netelip;1.2"
google_TTS Sueco (Suecia) sv-SE-Standard-D MASCULINO options: "google_TTS;sv-SE-Standard-D;Bienvenido a netelip;1.2"
google_TTS Sueco (Suecia) sv-SE-Standard-E MASCULINO options: "google_TTS;sv-SE-Standard-E;Bienvenido a netelip;1.2"
google_TTS Sueco (Suecia) sv-SE-Wavenet-A FEMENINO options: "google_TTS;sv-SE-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Sueco (Suecia) sv-SE-Wavenet-B FEMENINO options: "google_TTS;sv-SE-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Sueco (Suecia) sv-SE-Wavenet-C MASCULINO options: "google_TTS;sv-SE-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Sueco (Suecia) sv-SE-Wavenet-D FEMENINO options: "google_TTS;sv-SE-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Sueco (Suecia) sv-SE-Wavenet-E MASCULINO options: "google_TTS;sv-SE-Wavenet-E;Bienvenido a netelip;1.2"
google_TTS Tamil (India) ta-IN-Standard-A FEMENINO options: "google_TTS;ta-IN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Tamil (India) ta-IN-Standard-B MASCULINO options: "google_TTS;ta-IN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Tamil (India) ta-IN-Wavenet-A FEMENINO options: "google_TTS;ta-IN-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Tamil (India) ta-IN-Wavenet-B MASCULINO options: "google_TTS;ta-IN-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Telugu (India) te-IN-Standard-A FEMENINO options: "google_TTS;te-IN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Telugu (India) te-IN-Standard-B MASCULINO options: "google_TTS;te-IN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Tailandés (Tailandia) th-TH-Standard-A FEMENINO options: "google_TTS;th-TH-Standard-A;Bienvenido a netelip;1.2"
google_TTS Turco (Turquía) tr-TR-Standard-A FEMENINO options: "google_TTS;tr-TR-Standard-A;Bienvenido a netelip;1.2"
google_TTS Turco (Turquía) tr-TR-Standard-B MASCULINO options: "google_TTS;tr-TR-Standard-B;Bienvenido a netelip;1.2"
google_TTS Turco (Turquía) tr-TR-Standard-C FEMENINO options: "google_TTS;tr-TR-Standard-C;Bienvenido a netelip;1.2"
google_TTS Turco (Turquía) tr-TR-Standard-D FEMENINO options: "google_TTS;tr-TR-Standard-D;Bienvenido a netelip;1.2"
google_TTS Turco (Turquía) tr-TR-Standard-E MASCULINO options: "google_TTS;tr-TR-Standard-E;Bienvenido a netelip;1.2"
google_TTS Turco (Turquía) tr-TR-Wavenet- FEMENINO options: "google_TTS;tr-TR-Wavenet-;Bienvenido a netelip;1.2"
google_TTS Turco (Turquía) tr-TR-Wavenet-B MASCULINO options: "google_TTS;tr-TR-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Turco (Turquía) tr-TR-Wavenet-C FEMENINO options: "google_TTS;tr-TR-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Turco (Turquía) tr-TR-Wavenet-D FEMENINO options: "google_TTS;tr-TR-Wavenet-D;Bienvenido a netelip;1.2"
google_TTS Turco (Turquía) tr-TR-Wavenet-E MASCULINO options: "google_TTS;tr-TR-Wavenet-E;Bienvenido a netelip;1.2"
google_TTS Ucraniano (Ucrania) uk-UA-Standard-A FEMENINO options: "google_TTS;uk-UA-Standard-A;Bienvenido a netelip;1.2"
google_TTS Ucraniano (Ucrania) uk-UA-Wavenet-A FEMENINO options: "google_TTS;uk-UA-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Vietnamita (Vietnam) vi-VN-Standard-A FEMENINO options: "google_TTS;vi-VN-Standard-A;Bienvenido a netelip;1.2"
google_TTS Vietnamita (Vietnam) vi-VN-Standard-B MASCULINO options: "google_TTS;vi-VN-Standard-B;Bienvenido a netelip;1.2"
google_TTS Vietnamita (Vietnam) vi-VN-Standard-C FEMENINO options: "google_TTS;vi-VN-Standard-C;Bienvenido a netelip;1.2"
google_TTS Vietnamita (Vietnam) vi-VN-Standard-D MASCULINO options: "google_TTS;vi-VN-Standard-D;Bienvenido a netelip;1.2"
google_TTS Vietnamita (Vietnam) vi-VN-Wavenet-A FEMENINO options: "google_TTS;vi-VN-Wavenet-A;Bienvenido a netelip;1.2"
google_TTS Vietnamita (Vietnam) vi-VN-Wavenet-B MASCULINO options: "google_TTS;vi-VN-Wavenet-B;Bienvenido a netelip;1.2"
google_TTS Vietnamita (Vietnam) vi-VN-Wavenet-C FEMENINO options: "google_TTS;vi-VN-Wavenet-C;Bienvenido a netelip;1.2"
google_TTS Vietnamita (Vietnam) vi-VN-Wavenet-D MASCULINO options: "google_TTS;vi-VN-Wavenet-D;Bienvenido a netelip;1.2"

Voice to Text

Para poder usar el servicio de Google se deben seguir estos pasos:

1 Ir a la consola de Google Cloud

2 Habilitar el producto y servicio "Google Cloud Speech API"

3 Acceder a 'APIs y servicios -> Credenciales' y crear una clave de API. Para restringir el acceso por IP a la key generada para la API se debe pulsar sobre ella y añadir la IP, por ejemplo la ip de apivoice 185.8.244.102.

4 Obtenida la key ya está listo para añadirlo como parámetro en el comando.

Tabla de idiomas de reconocimiento de voz de Google:

País Idioma Código
Afrikaans af-ZA
Indonesia Bahasa Indonesia id-ID
Malasia Bahasa Melayu ms-MY
España Català ca-ES
Rep. Checa Čeština cs-CZ
Alemania Deutsch de-DE
Australia English en-AU
Canada English en-CA
India English en-IN
New Zealand English en-NZ
South Africa English en-ZA
United Kingdom English en-GB
United States English en-US
Argentina Español es-AR
Bolivia Español es-BO
Chile Español es-CL
Colombia Español es-CO
Costa Rica Español es-CR
Ecuador Español es-EC
El Salvador Español es-SV
España Español es-ES
Estados Unidos Español es-US
Guatemala Español es-GT
Honduras Español es-HN
México Español es-MX
Nicaragua Español es-NI
Panamá Español es-PA
Paraguay Español es-PY
Perú Español es-PE
Puerto Rico Español es-PR
República Dominicana Español es-DO
Uruguay Español es-UY
Venezuela Español es-VE
Euskara eu-ES
Français fr-FR
Galego gl-ES
Hrvatski hr_HR
IsiZulu zu-ZA
Íslenska is-IS
Italia Italiano it-IT
Svizzera Italiano it-CH
Magyar hu-HU
Nederlands nl-NL
Norsk bokmål nb-NO
Polski pl-PL
Brasil Português pt-BR
Portugal Português pt-PT
Română ro-RO
Slovenčina sk-SK
Suomi fi-FI
Svenska sv-SE
Türkçe tr-TR
български bg-BG
Pусский ru-RU
Српски sr-RS
한국어 ko-KR
普通� (中国大�) 中文 cmn-Hans-CN
普通� (香港) 中文 cmn-Hans-HK
中文 (台灣) 中文 cmn-Hant-TW
�語 (香港) 中文 yue-Hant-HK
日本語 ja-JP
Lingua latīna la

Caso práctico

Flujo de llamada recibida

Para ver el funcionamiento de API Voice se muestra a continuación el flujo de una llamada recibida. Las peticiones que realiza API Voice se indican con "P:" y las respuestas del controlador del cliente con "R:".

P: Recepción de llamada

Petición #1:

{
   "ID": "1576556033.1735",
   "api": "API 13a05",
   "src": "638829213",
   "dst": "34951504990",
   "startcall": "2019-11-14 11:04:26",
   "typesrc": "did",
   "usersrc": "638829213"
}

API Voice recibe una llamada y realiza una petición a su URL de control de llamadas con todos los datos en POST.

R: Locución de espera

Respuesta #1:

{
   "command"  : "speak",
   "options"  : "google;es;Espere por favor.",
   "userfield": "1"
}

El controlador recibe los datos de la llamada y le contesta a API Voice para que reproduzca una locución a partir del text con el comando speak.

P: Espera terminada

Petición #2:

{
   "ID": "1576556033.1735",
   "api": "API 13a05",
   "src": "638829213",
   "dst": "34951504990",
   "startcall": "2019-11-14 11:04:26",
   "typesrc": "did",
   "usersrc": "638829213",
   "command": "speak", 
   "options": "google;es;Espere por favor.",
   "userfield": "1",
   "description": "OK",
   "statuscode": "200",
   "startcall": "2019-11-14 11:04:26",
   "durationcall": "3",
   "durationcallanswered": "", 
   "statuscall": "ANSWER", 
   "channel": "U5lQL1MTMy0wNDAwNGMlNQ==",
   "typesrc": "did",
   "usersrc": "683282931"
}

API Voice reproduce el texto y envía una nueva petición con el estado de la llamada.

API Voice copia los tres parámetros command, options y userfield tal como los recibió para que el controlador pueda saber que es lo último que hizo.

R: Grabar la llamada

Respuesta #2:

{
   "command": "record",
   "options": "",
   "userfield": "2"
}

El controlador responde a API Voice indicando que active la grabación de la llamada.

P: Grabando

Petición #3:

{
   "ID": "1576556033.1735",
   "api": "API 13a05",
   "src": "638829213",
   "dst": "34951504990",
   "userfield": "2",
   "command": "record", 
   "options": "",
   "description": "OK",
   "statuscode": "200",
   "startcall": "2019-11-14 11:04:26",
   "durationcall": "4",
   "durationcallanswered": "",
   "dtmf": "",
   "statuscall": "ANSWER",
   "channel": "U5lQL1MTMy0wNDAwNGMlNQ==",
   "typesrc": "did",
   "usersrc": "638829213"
}

API Voice activa la grabación de la llamada, crea el fichero de audio y envía una petición a su URL de control de llamadas con la información de la llamada y el comando ejecutado.

R: Identificador de llamada

Respuesta #3

{
   "command": "callerid",
   "options": "638829213;34951504990",
   "userfield":"3"
}

El controlador indica a API Voice que cambie el identificador de llamada.

P: Identificador cambiado

Petición #4

{
   "ID": "1576556033.1735",
   "api": "API 13a05",
   "src": "638829213",
   "dst": "34951504990",
   "userfield": "3",
   "command": "callerid", 
   "options": "638829213;34951504990",
   "description": "CallerID is updated 34951504990",
   "statuscode": "200",
   "startcall": "2019-11-14 11:04:26",
   "durationcall": "4",
   "durationcallanswered": "",
   "dtmf": "",
   "statuscall": "ANSWER",
   "channel": "U5lQL1MTMy0wNDAwNGMlNQ==",
   "typesrc": "did",
   "usersrc": "638829213"
}

API Voice cambia el identificador de llamada y envía una petición a su controlador indicando el estado de la llamada y espera nuevo comando.

R: Realizar una llamada

Respuesta #4

{
   "command": "dial",
   "options": "pstn,655443322,60",
   "userfield": "4"
}

El controlador responde indicando a API Voice que realice una llamada a un número de la red pública.

P: Llamada terminada

Petición #4: NOANSWER

{
   "ID": "1576556033.1735",
   "api": "API 13a05",
   "src": "638829213",
   "dst": "34951504990",
   "userfield": "4",
   "command": "dial", 
   "options": "pstn,655443322,60",
   "description": "NOANSWER",
   "statuscode": "200",
   "startcall": "2019-11-14 11:04:26",
   "durationcall": "64",
   "durationcallanswered": "",
   "dtmf": "",
   "statuscall": "ANSWER",
   "channel": "U5lQL1MTMy0wNDAwNGMlNQ==",
   "typesrc": "did",
   "usersrc": "638829213"
}

Petición #4: ANSWER

{
   "ID": "1576556033.1735",
   "api": "API 13a05",
   "src": "638829213",
   "dst": "34951504990",
   "userfield": "4",
   "command": "dial", 
   "options": "pstn,655443322,60",
   "description": "ANSWER",
   "statuscode": "200",
   "startcall": "2019-11-14 11:04:26",
   "durationcall": "96",
   "durationcallanswered": "92",
   "dtmf": "",
   "statuscall": "ANSWER",
   "channel": "U5lQL1MTMy0wNDAwNGMlNQ==",
   "typesrc": "did",
   "usersrc": "638829213"
}

Una vez que API Voice realiza la llamada enviará el resultado de ésta en una petición a su URL de control de llamadas.

El el campo description se indicará el resultado de la llamada realizada por el comando dial.

Los campos durationcall y durationcallanswered reflejarán la duración de la llamada.

Terminada la llamada API Voice envía la petición y espera la siguiente orden.

R: Colgando la llamada

Respuesta #5

{
   "command": "hangup",
   "options": "",
   "userfield":""
}

El controlador recibe el estado de la llamada realizada por API Voice e indica que se debe colgar la llamada y terminar el flujo de peticiones.

Flujo de llamada realizada desde lanzador

Para ver el funcionamiento de API Voice se muestra a continuación el flujo de una llamada realizada desde el lanzador de llamadas del cliente. Las peticiones que realiza API Voice se indican con "P:", las respuestas del controlador del cliente con "R:", las peticiones del script del lanzador de llamadas del cliente "PC:" y la respuesta de API Voice al lanzador "RC".

PC: script de lanzador de llamada

Petición #1

<?php
$url="https://api.netelip.com/v1/voice";
$data=array(
   "token"=>"06d636492dc510e3e84884f886691766af15d8c58181d4178d79aba85181ab3d",
   "api"=>"API eaba7",
   "src"=>"34851000127",
   "dst"=>"100",
   "typedst"=>"extension",
   "duration"=>60,
   "userdata"=>"1");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result_curl= curl_exec($ch);
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close($ch);
echo $result_curl;
error_log($result_curl);
?>

RC: Lanzada la llamada

Respuesta #1

{
   "response": "200",
   "ID": "1671637004.1996"
}

En caso de recuperar un valor disinto de 200 en "response" y no obtener "ID", es porque ha ocurrido un error. Para más información sobre errores acceder a la sección Errores.

P: Recepción de llamada

Petición #2:

{
   "ID": "1671637004.1996",
   "api": "API eaba7",
   "src": "34851000127",
   "dst": "100",
   "startcall": "2022-12-21 16:52:54",
   "userdata": "1"
}

API Voice recibe una llamada y realiza una petición a su URL de control de realización de llamadas con todos los datos en POST.

R: Cambio de idioma

Respuesta #2:

{
   "command"  : "language",
   "options"  : "es",
   "userfield": "1"
}

El controlador recibe los datos de la llamada y le contesta a API Voice para que cambie el idioma de las posibles locuciones con el comando language.

P: Cambiando de idioma

Petición #3:

{
   "ID": "1671637004.1996",
   "api": "API eaba7",
   "src": "34851000127",
   "dst": "100",
   "userfield": "1",
   "command": "language",
   "options": "es",
   "description": "OK",
   "statuscode": "200",
   "startcall": "2022-12-21 16:52:54",
   "durationcall": "6",
   "durationcallanswered": "",
   "statuscall": "ANSWER",
   "userdata": "1",
}

API Voice cambia el idioma en la llamada y envía una petición a su controlador indicando el estado de la llamada y espera nuevo comando.

R: Hacemos llamada al número de teléfono

Respuesta #3:

{
   "command"  : "dial",
   "options"  : "pstn,0034638829213,20",
   "userfield": "2"
}

P: Haciendo la llamada

Petición #4:

{
   "ID": "1671637004.1996",
   "api": "API eaba7",
   "src": "34851000127",
   "dst": "100",
   "userfield": "2",
   "command": "dial",
   "options": "pstn,0034638829213,20",
   "startcall": "2022-12-21 16:53:18",
   "durationcall": "0",
   "durationcallanswered": "7",
   "userdata": "1",
}

El controlador recibe los datos de la llamada y le contesta a API Voice para que llame al numero de teléfono 0034638829213 con el comando dial.

R: Colgamos la llamada

Respuesta #4:

{
   "command"  : "hangup",
   "options"  : "",
   "userfield": ""
}

El controlador recibe los datos de la llamada y le contesta a API Voice para que cuelgue la llamada con el comando hangup y terminar el flujo de peticiones.

Ejemplos de apps de APIVoice

Se solicita un código apara acceder al menú del servicio

La aplicación de APIVoice controla el acceso a usuarios de un servicio telefónico solicitando al usuario que llama un código de acceso. El script se colocará en la URL recepción de llamadas.

# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación. 
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
// Obtenemos los datos de la llamada y las guardamos en variables
$src = $_POST["src"];
$dst = $_POST["dst"];
$id = $_POST["ID"];

if ($src == "" || $dst == "" || $id != "") die(); // Algo está mal, terminamos

$dtmf = $_POST["dtmf"];

// Datos del ultimo comando ejecutado si no estamos al comienzo de una llamada
$command = $_POST["command"];
$options = $_POST["options"];
$userfield = ($_POST["userfield"] == "") ? "1" : $_POST["userfield"];

$messages = array(
   1 => "Bienvenido a mi empresa, por favor escriba a continuacion su usuario.",
   2 => "Su usuario es correcto, accedemos al menu del servicio.",
   3 => "Su usuario es incorrecto, para acceder a este servicio debes de ser usuario.",
   4 => "Pulse uno para hablar con atencion al cliente, pulse dos, para hablar con soporte.",
);

switch($userfield) {

   case "0": // colgamos la llamada
      $command = "hangup";
      $options = "";
      $userfield = "";
      break;

   case "1": // reproducimos una locucion esperando una respuesta
      $command = "speak_getdtmf";
      $options  = "google;es;".$messages[1].";5000;4;1.2";
      $userfield = "2";
      break;

   case "2":
      $command = "speak_getdtmf";
      switch($dtmf) {

         case "timeout": // tiempo agotado, locucion y repetimos
            $options = "netelip;Pedro;".$messages[1].";5000;4";
            $userfield = "2";
            break;

         case("1111"): // usuario correcto, locucion y a la cola
            $options = "netelip;Pedro;".$messages[2].$messages[4].";5000;1";
            $userfield = "3";
            break;

         default: // usuario incorrecto, locución de despedida y colgamos
            $command = "speak";
            $options = "netelip;Pedro;".$messages[3];
            $userfield = "0";
         }
      }
      break;

   case "3":
      $command = "queue";
      $userfield = "0";
      switch($dtmf) {

         case "timeout": // tiempo agotado, locucion y repetimos
            $command = "speak_getdtmf";
            $options = "netelip;Pedro;".$messages[4].";5000;1";
            $userfield = "3";
            break;

         case "1": // ejecutamos la cola de atencion de la vPBX con prioridad 2
            $options = "colaatencion;2";
            break;

         case "2": // ejecutamos la cola de soporte de la vPBX con prioridad 1
            $options = "colasoporte;1";
            break;
      }
      break;
}

$cadena = array("command"=>$comand, "options"=>$options, "userfield"=>$userfield);
echo(json_encode($cadena));
?>
#!/usr/bin/env python

messages = [
   'Bienvenido a mi empresa, por favor escriba a continuacion su usuario.',
   'Su usuario es correcto, accedemos al menu del servicio.',
   'Su usuario es incorrecto, para acceder a este servicio debes de ser usuario.',
   'Pulse uno para hablar con atencion al cliente, pulse dos, para hablar con soporte.',
]

from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/controller', methods=['GET','POST'])
def controller():

    if request.method == 'POST':
        # Obtenemos los datos de la llamada y las guardamos en variables
        src = request.form.get('src')
        dst = request.form.get('dst')
        idc = request.form.get('ID')

        if src == None or dst == None or idc == None: 
            return jsonify(error='No se han definido argumentos')
        if src == "" or dst == "" or idc == "": 
            return jsonify(error='Los argumentos no pueden ir vacios')

        dtmf = request.form.get("dtmf")

        # Datos del ultimo comando ejecutado
        c = {
            'command'  : request.form.get("command"),
            'options'  : request.form.get("options"),
            'userfield': request.form.get("userfield")
        }

        if c['userfield'] == "0": # colgamos la llamada
            c['command'] = "hangup"
            c['options'] = ""
            c['userfield'] = ""

        elif c['userfield'] == "1" or c['userfield'] == "" or c['userfield'] == None: 
            # reproducimos una locucion esperando una respuesta (llamada entrante)
            c['command'] = "speak_getdtmf"
            c['options'] = "google;es;%s;5000;4;1.2" % messages[0]
            c['userfield'] = "2"

        elif c['userfield'] == "2":
            c['command'] = "speak_getdtmf"

            if dtmf == "timeout": # tiempo agotado, locucion y repetimos
                c['options'] = "netelip;Pedro;%s;5000;1" % messages[0]
                c['userfield'] = "2"

            elif dtmf == "1111": # usuario correcto, locucion y a la cola
                c['options'] = "netelip;Pedro;%s%s;5000;1" % (messages[1], messages[3])
                c['userfield'] = "3"

            else: # usuario incorrecto, locución de despedida y colgamos
                c['command'] = "speak"
                c['options'] = "netelip;Pedro;%s" % messages[2]
                c['userfield'] = "0"

        elif c['userfield'] == "3":
            c['command'] = "queue"
            c['userfield'] = "0"

            if dtmf == "timeout": # tiempo agotado, locucion y repetimos
                c['command'] = "speak_getdtmf"
                c['options'] = "netelip;Pedro;%s;5000;1" % messages[3]
                c['userfield'] = "3"

            elif dtmf == "1": # ejecutamos la cola de atencion de la vPBX con prioridad 2
                c['options'] = "colaatencion;2"

            elif dtmf == "2": # ejecutamos la cola de soporte de la vPBX con prioridad 1
                c['options'] = "colasoporte;1"

        print(jsonify(c))
        return jsonify(c)
    else:
        return jsonify(error='Metodo no permitido')   

if __name__ == '__name__':
   app.run()

Lanzador de llamada a un número de teléfono

La aplicación de APIVoice lanza una llamada a un número de teléfono (a esta aplicación le faltaría el script correspondiente a la URL realización de llamadas).

curl -X POST https://api.netelip.com/v1/voice \
  --data "token=11111112222222" \
  --data "api=Mi API" \
  --data "src=34951223344" \
  --data "dst=0034666554433" \
  --data "duration=30" \
  --data "typedst=pstn"
<?php
$url="https://api.netelip.com/v1/voice";
$post = array(
   "token"     => "11111112222222",
   "api"       => "Mi API",
   "src"       => "34951223344",
   "dst"       => "0034666554433",
   "duration"  => "30",
   "typedst"   => "pstn",
);

$request = curl_init($url);
curl_setopt($request, CURLOPT_POST, 1);
curl_setopt($request, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($request, CURLOPT_POSTFIELDS, $post);
curl_setopt($request, CURLOPT_RETURNTRANSFER, 1);

$response = curl_exec($request);
$response_code = curl_getinfo($request, CURLINFO_HTTP_CODE);
if ($response !== false) {
   if ($response_code == 200) {
      echo $response;   
   }
} else {
   echo "Error: ".$response_code;
}

curl_close($request);
?>
#!/usr/bin/env python

import requests

url = 'https://api.netelip.com/v1/voice'
data = {
    'token'    : '11111112222222',
    'api'      : 'Mi API',
    'src'      : '34951223344',
    'dst'      : '0034666554433',
    'duration' : '30',
    'typedst'  : 'pstn',
}

response = requests.post(url=url, data=data, timeout=(5, 5), max_redirects=3)

if response:
   if response.status_code == 200:
      print(response.text)
else:
    print("Error: %s" % $response.status_code)

Llamada a un contacto de nuestro listado

La aplicación de APIVoice llama a nuestra extensión y una vez contestada conectará con el número de teléfono de nuestro contacto. Script en nuestro lanzador de llamadas

curl -X POST https://api.netelip.com/v1/voice \
  --data "token=11111112222222" \
  --data "api=Mi API" \
  --data "src=34951223344" \
  --data "dst=100" \
  --data "duration=30" \
  --data "typedst=extension" \
  --data "userdata=0034666554433"
<?php
$url="https://api.netelip.com/v1/voice";
$data=array(
   "token"=>"11111112222222",
   "api"=>"Mi API",
   "src"=>"34951223344",
   "dst"=>"100",
   "typedst"=>"extension",
   "duration"=>30,
   "userdata"=>"0034666554433");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result_curl= curl_exec($ch);
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close($ch);
echo $result_curl;
error_log($result_curl);
?>

Script de la URL realización de llamadas

# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación. 
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
$telefono=$_POST["userdata"];
if ($_POST["userfield"]=="")
   {
   $userfield="0";
   }
else
   {
   $userfield=$_POST["userfield"];
   }
switch($userfield)
   {
   case "0":
      $cadena=array("command"=>"language","options"=>"es","userfield"=>"1");
   break;
   case "1":
      $cadena=array("command"=>"dial","options"=>"pstn,".$telefono.",20,calling,36000","userfield"=>"2");
   break;
   case "2":
      $cadena=array("command"=>"hangup","options"=>"","userfield"=>"");
   break;
   }
echo json_encode($cadena);
?>

Llamada a un contacto de nuestro listado con cambio de identificador de llamada

La aplicación de APIVoice llama a nuestra extensión y una vez contestada conectará con el número de teléfono de nuestro contacto modificando antes el identificador de llamada que se le mostrará.

Script en nuestro lanzador de llamadas

curl -X POST https://api.netelip.com/v1/voice \
  --data "token=11111112222222" \
  --data "api=Mi API" \
  --data "src=34951223344" \
  --data "dst=100" \
  --data "duration=30" \
  --data "typedst=extension" \
  --data "userdata=0034666554433"
<?php
$url="https://api.netelip.com/v1/voice";
$data=array(
   "token"=>"11111112222222",
   "api"=>"Mi API",
   "src"=>"34951223344",
   "dst"=>"100",
   "typedst"=>"extension",
   "duration"=>30,
   "userdata"=>"0034666554433");
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_MAXREDIRS, 3);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_POST, TRUE);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
$result_curl= curl_exec($ch);
$http_code = curl_getinfo( $ch, CURLINFO_HTTP_CODE );
curl_close($ch);
echo $result_curl;
error_log($result_curl);
?>

Script de la URL realización de llamadas

# Se puede capturar una petición HTTP con lenguajes scripts como bash, perl, etc.
#
# Pero se recomienda usar lenguajes como php o python para realizar esta tarea
# ya que están orientados a servicios web y puede encontrar más documentación. 
#
# Elija el lenguaje php o python en las pestañas superiores para ver el ejemplo
# de un controlador.
#
# Si aún así lo necesita debe configurar correctamente su servidor web para ejecutar
# scripts (CGI).
<?php
$telefono=$_POST["userdata"];
$callerid="netelip;XXXXXXXXXXX";
if ($_POST["userfield"]=="")
   {
   $userfield="0";
   }
else
   {
   $userfield=$_POST["userfield"];
   }
switch($userfield)
   {
   case "0":
      $cadena=array("command"=>"language","options"=>"es","userfield"=>"1");
   break;
   case "1":
      $cadena=array("command"=>"callerid","options"=>$callerid,"userfield"=>"2");
   break;
   case "2":
      $cadena=array("command"=>"dial","options"=>"pstn,".$telefono.",20,calling,36000","userfield"=>"3");
   break;
   case "3":
      $cadena=array("command"=>"hangup","options"=>"","userfield"=>"");
   break;
   }
echo json_encode($cadena);
?>