https://tu-servidor.neervox.com/api/externo/v1
Integra tu CRM con el IVR de NeervoX
Una API REST para lanzar campañas de voz masivas, cargar contactos con sus datos y recuperar el resultado de cada llamada — todo desde tu propio sistema, sin que nadie entre a la interfaz.
Qué es esta API
El IVR de NeervoX marca miles de teléfonos por hora y reproduce un mensaje de voz. Esta API deja que tu CRM opere ese motor: crear la campaña, cargar a quién llamar con el RUT y los datos que quieras, arrancarla, y después leer cómo terminó cada llamada para cruzarla contra tu base.
Todo se hace con peticiones HTTP a la URL base. Cada respuesta es JSON. No hay SDK que instalar: sirve curl, fetch, la librería HTTP de tu lenguaje o cualquier cliente REST.
tu-servidor.neervox.com/api/externo/v1X-API-KeyAutenticación
Cada petición lleva tu llave de API en la cabecera X-API-Key. Sin ella la respuesta es 401.
La llave la genera un administrador desde la interfaz de NeervoX (sección Integraciones). Se muestra una sola vez al crearla — guárdala en un lugar seguro; en el servidor solo queda su huella, así que si se pierde hay que generar otra.
Dos niveles de permiso
| Permiso | Puede | No puede |
|---|---|---|
lectura |
Consultar campañas, reportes, salud de carriers, listas, resultados. | Crear, modificar, cargar contactos, arrancar ni detener. |
escritura |
Todo lo de lectura, más crear campañas, cargar contactos, arrancar, detener, subir audios. | Administrar llaves (eso es solo desde la interfaz). |
Una llave de solo lectura que intente escribir recibe 403. Da a cada integración el permiso mínimo que necesita.
# Toda petición lleva la llave en la cabecera curl https://tu-servidor.neervox.com/api/externo/v1/ping \ -H "X-API-Key: nvx_a1b2c3d4e5f6..."
Tu primera llamada
El endpoint /ping confirma que la llave sirve. Es lo primero que conviene probar al integrar.
curl https://tu-servidor.neervox.com/api/externo/v1/ping \ -H "X-API-Key: TU_LLAVE" # Respuesta 200 { "ok": true, "servicio": "IVR NeervoX", "momento": "2026-09-16T01:31:20.221Z" }
Si en vez de eso recibes 401 Unauthorized, la llave falta o es incorrecta. Si recibes 403 Forbidden, la llave existe pero no tiene el permiso que ese endpoint exige.
Errores y límites
La API usa los códigos HTTP estándar. El cuerpo de un error trae siempre un message legible que explica qué pasó.
| Código | Significa | Qué hacer |
|---|---|---|
200 / 201 | Todo salió bien. | — |
400 | Algo en la petición está mal (falta un campo, un formato inválido, una lista vacía). | Lee el message: dice exactamente qué corregir. |
401 | Falta la llave o es inválida. | Revisa la cabecera X-API-Key. |
403 | La llave no tiene permiso de escritura. | Usa una llave de escritura para ese endpoint. |
404 | El recurso (campaña, lista…) no existe. | Verifica el id. |
500 | Error interno. Queda registrado del lado del servidor. | Reintenta; si persiste, reporta el momento exacto. |
Ejemplo de error
# 400 al cargar una lista sin números utilizables { "message": "Ninguno de los números recibidos es utilizable.", "error": "Bad Request", "statusCode": 400 }
Límites
- Hasta 250.000 contactos por carga (unas 12 MB con RUT). Para más, divide en varias cargas usando el mismo
lista_id: se suman a la misma lista. - El cuerpo de la petición admite hasta 25 MB.
- Los teléfonos y RUT se normalizan solos: un
912345678se guarda como56912345678, y el RUT se valida con su dígito verificador.
Flujo completo de una integración
El caso típico: tu CRM crea una campaña, le carga a quién llamar, la arranca y después lee el resultado. Cinco pasos.
-
Elegir un árbol de voz
Una campaña necesita un árbol publicado (el mensaje que se reproduce). Lístalos y guarda el
iddel que vas a usar.GET/arboleslectura -
Crear la campaña
Queda en borrador (
DRAFT): no hace sonar ningún teléfono hasta que le cargues números y la arranques. Es deliberado — evita un envío por accidente.POST/campanasescritura{ "nombre": "Cobranza septiembre", "flow_id": "<id del árbol>", "max_channels": 300, "cps": 10, "max_intentos": 2, "espera_reintento_min": 180, "hora_inicio_diaria": "09:00", "hora_fin_diaria": "19:00" } -
Cargar los contactos
Manda el teléfono con los datos que quieras recuperar después (RUT, nombre, lo que traiga tu base). Se descartan solos los repetidos, los que no parecen teléfono, los que ya se sabe que no existen y los que pidieron no ser llamados.
POST/campanas/{id}/contactos-con-datosescritura -
Revisar y arrancar
Antes de arrancar puedes ver una muestra de lo que va a discar con
GET /campanas/{id}/muestra. Cuando estés listo, arráncala: a partir de aquí suenan teléfonos de verdad.POST/campanas/{id}/arrancarescritura -
Leer el resultado
Mientras disca, consulta el avance con
/campanas/{id}/reporte. Al terminar, baja el resultado llamada por llamada — cada uno trae de vuelta el RUT y los datos que mandaste, para cruzar contra tu CRM.GET/campanas/{id}/resultadoslectura
DRAFT (recién creada, no disca) →
RUNNING (discando) →
PAUSED (detenida, se retoma donde iba) →
DONE (terminó). Detener y volver a arrancar es seguro: lo pendiente se retoma.
Cargar contactos con datos
La forma útil para un CRM: cada teléfono viaja con un objeto extra — RUT, nombre, deuda, lo que sea — que vuelve intacto junto al resultado de la llamada.
curl -X POST https://tu-servidor.neervox.com/api/externo/v1/campanas/{id}/contactos-con-datos \ -H "X-API-Key: TU_LLAVE" \ -H "Content-Type: application/json" \ -d '{ "lista": "Morosos septiembre", "contactos": [ { "numero": "912345678", "extra": { "rut": "12345678-5", "nombre": "Juan Pérez" } }, { "numero": "987654321", "extra": { "rut": "9876543-3", "deuda": "45000" } } ] }' # Respuesta 201 — cada descarte dice POR QUÉ { "recibidos": 2, "cargados": 2, "repetidos": 0, "no_parecen_numero": 0, "ya_estaban": 0, "no_existen": 0, "dados_de_baja": 0, "lista": { "id": "a1b2...", "nombre": "Morosos septiembre" } }
Listas dentro de una campaña
Cada carga es una lista con nombre propio. Todas comparten el árbol, el carrier y el horario de la campaña, pero se pueden pausar y medir por separado. Para sumar contactos a una lista que ya existe, manda su lista_id en vez de lista.
extra vuelven en datos al leer los resultados. Ese es el punto de todo esto: cruzar la gestión contra tu propia base sin buscar número por número.
Leer los resultados
Cada fila es un intento, no una persona: si a alguien se le llamó dos veces, aparecen sus dos llamadas con su número de intento. Los datos que cargaste vuelven en datos.
Acepta ?desde= (fecha ISO, para traer solo lo nuevo desde tu última consulta), ?limite= (máximo 2000) y ?detalle=1 (agrega códigos de cuelgue, calidad, recorrido por el árbol y las columnas de tu Excel).
# Sondeo incremental: cada X minutos, trae lo nuevo curl ".../campanas/{id}/resultados?desde=2026-09-16T00:00:00Z&detalle=1" \ -H "X-API-Key: TU_LLAVE" # Respuesta 200 — un objeto por intento [ { "numero": "56912345678", "contesto": true, "resultado": "COMPLETED", "duracion_seg": 30, "escucho_completo": true, "audio_segundos": 30, "teclas": null, "transferida": false, "pidio_baja": false, "momento": "2026-09-16T13:10:28.796Z", "datos": { "rut": "12345678-5", "nombre": "Juan Pérez" } } ]
?desde= apuntando a tu última lectura, y procesa solo lo nuevo. Guarda el momento del último registro que viste para la próxima consulta.
No molestar
Quien pidió no ser llamado no debe recibir llamadas — vengan de donde vengan. La API respeta esa lista en toda carga y te deja consultarla y alimentarla.
Consulta si un número pidió no ser llamado, antes de cargarlo.
Registra una baja que recibiste por otro canal (tu call center, tu web). Cuerpo: { "numero": "...", "motivo": "..." }.
dados_de_baja.
Referencia · Campañas
Todas las campañas, con estado, avance y contadores. Es de donde tu CRM saca los id.
[
{
"id": "c3a1f0e2-...",
"nombre": "Campaña de ejemplo",
"estado": "DONE",
"arbol": "Árbol de ejemplo",
"cargados": 50000,
"discadas": 50000,
"contestadas": 11500,
"pendientes": 0,
"creada": "2026-01-15T09:00:00.000Z"
}
]
Estado de una campaña: cargados, discadas, contestadas, pendientes.
Crea una campaña (queda en DRAFT). Requiere nombre y flow_id; el resto es opcional con valores por defecto sensatos.
Cambia ritmo, horario, carrier o árbol. Se aplica en la vuelta siguiente, sin detener la campaña.
arrancar hace sonar teléfonos de verdad. detener pausa; lo pendiente se retoma donde iba.
Qué va a discar exactamente, para revisarlo antes de arrancar. Acepta ?limite=.
Cómo va ahora mismo: en curso, pendientes, últimas llamadas.
Referencia · Contactos y listas
Carga contactos con su objeto extra. La forma recomendada para un CRM. Ver detalle arriba →
Carga simple, solo teléfonos: { "numeros": ["912345678", ...] }. Hasta 250.000 por llamada.
Las cargas de la campaña. llamados = recibieron al menos una llamada (aunque esperen un reintento); cerrados = a los que ya no se llamará más.
Crea una lista vacía para cargarle números después: { "nombre": "Lote A" }.
Pausa o reanuda una lista: { "activa": false }. Pausar no borra: los números y su historial quedan.
Referencia · Reportes
Los mismos datos que ve la interfaz. Cada porcentaje viene con la base sobre la que está calculado — "25%" no significa lo mismo sobre lo cargado que sobre lo efectivamente llamado.
Lo que pasa ahora en todas las campañas: en curso, ritmo, consolidado del día.
Cómo se repartió la jornada de hoy, hora a hora.
Resumen con cada tasa y su base: contacto, cobertura, avance, reintentos.
{
"cargados": 50000,
"discadas": 50000,
"intentos": 72000,
"reintentos": 22000,
"contestadas": 11500,
"tasas": {
"contacto": { "valor": 23, "sobre": "personas llamadas" },
"cobertura": { "valor": 23, "sobre": "contactos cargados" }
}
}
El reporte operativo: quién cortó primero, cuánto del mensaje se escuchó, rendimiento por intento, tiempo hasta contestar y motivos de no-contacto.
Qué tecla marcó la gente; por dónde pasó dentro del árbol y dónde se fue cayendo; comportamiento hora a hora.
Campañas lado a lado: cuál rindió mejor. Acepta ?minimo= (excluye campañas con pocas llamadas).
Referencia · Salud de carriers
Cómo responde cada carrier ahora mismo: estado (SANO/ALERTA/CAIDO/SIN_DATOS), tasa de contacto y duración media.
El acumulado de cada carrier en el periodo, con su día a día. Acepta ?dias= (por defecto 30).
La serie de un carrier: la tendencia dice más que el momento. Acepta ?dias=.
Referencia · Audios y árboles
Los árboles de voz disponibles, para elegir con cuál disca una campaña.
Un árbol con sus nodos y conexiones.
Los audios disponibles para usar en un árbol.
Sube un audio (multipart/form-data, campo file). Se convierte al formato que la central necesita — subirlo crudo dejaría la llamada muda, así que la conversión no es opcional.
Todos los endpoints
Los 32 endpoints de la v1, de un vistazo.
| Método y ruta | Qué hace | Permiso |
|---|---|---|
GET/ping | Comprueba la llave | lectura |
GET/campanas | Lista campañas | lectura |
GET/campanas/{id} | Estado de una campaña | lectura |
POST/campanas | Crea campaña (queda en borrador) | escritura |
PATCH/campanas/{id} | Cambia ritmo, horario, carrier, árbol | escritura |
POST/campanas/{id}/arrancar | Empieza a discar | escritura |
POST/campanas/{id}/detener | Pausa la campaña | escritura |
GET/campanas/{id}/muestra | Qué va a discar (antes de arrancar) | lectura |
GET/campanas/{id}/en-vivo | Cómo va ahora mismo | lectura |
POST/campanas/{id}/contactos-con-datos | Carga contactos con RUT y datos | escritura |
POST/campanas/{id}/contactos | Carga solo teléfonos | escritura |
GET/campanas/{id}/listas | Las cargas de la campaña | lectura |
POST/campanas/{id}/listas | Crea una lista vacía | escritura |
PATCH/listas/{listaId} | Pausa o reanuda una lista | escritura |
GET/campanas/{id}/resultados | Resultado llamada por llamada | lectura |
GET/bajas/{numero} | ¿Pidió no ser llamado? | lectura |
POST/bajas | Registra una baja | escritura |
GET/operacion | Panorama en vivo | lectura |
GET/operacion/por-hora | La jornada de hoy, hora a hora | lectura |
GET/campanas/{id}/reporte | Resumen con tasas y bases | lectura |
GET/campanas/{id}/reporte/supervisor | Reporte operativo detallado | lectura |
GET/campanas/{id}/reporte/teclas | Qué tecla marcó la gente | lectura |
GET/campanas/{id}/reporte/embudo | Recorrido por el árbol | lectura |
GET/campanas/{id}/reporte/por-hora | Comportamiento hora a hora | lectura |
GET/reportes/comparar | Campañas lado a lado | lectura |
GET/carriers/salud | Estado de cada carrier ahora | lectura |
GET/carriers/historico | Acumulado del periodo, día a día | lectura |
GET/carriers/{id}/tendencia | La serie de un carrier | lectura |
GET/arboles | Árboles de voz disponibles | lectura |
GET/arboles/{id} | Un árbol con sus nodos | lectura |
GET/audios | Audios disponibles | lectura |
POST/audios | Sube un audio | escritura |