VVoiceOps AI

API y webhooks

Versión 1.0 · 10 de noviembre de 2026

Disponibles en el plan Business. Las claves y los webhooks se gestionan en la plataforma, en Integraciones.

Autenticación

Envía tu clave en la cabecera Authorization: Bearer vo_live_…. Cada clave tiene permisos acotados y pertenece a una sola organización. Límite: 120 peticiones por minuto y clave (429 al superarlo). La clave se muestra una vez al crearla; puedes rotarla o revocarla en cualquier momento. Las claves no pueden gestionar usuarios ni escuchar grabaciones.

curl https://voiceopsai.cybernetix.es/api/v1/calls?limit=20 \
  -H "Authorization: Bearer vo_live_XXXXXXXX"

Endpoints

MétodoRutaPermisoQué hace
GET/api/v1/callscalls.readLista llamadas (filtros status, direction; paginación con before)
GET/api/v1/calls/{uuid}calls.readDetalle: conversación, resumen, métricas por turno, transferencias
GET/api/v1/agentsagents.readLista de agentes
GET/api/v1/appointmentsappointments.readCitas por rango (from, to en AAAA-MM-DD)
GET/api/v1/appointments/availability?date=appointments.readHuecos libres de un día
POST/api/v1/appointmentsappointments.manageCrea una cita (date, time, name, phone, service)
GET/api/v1/contactsappointments.readContactos
POST/api/v1/contactsappointments.manageCrea un contacto
GET/api/v1/ticketsappointments.readBandeja: incidencias, recados y devoluciones
GET/api/v1/automationsautomations.readAutomatizaciones
POST/api/v1/automations/{uuid}/runautomations.manageEjecuta una automatización (mode: test | real)

Los errores siguen el formato {"error":{"code","message","details"}}. Las fechas van en ISO 8601 (UTC) salvo que se indique lo contrario.

Webhooks

Recibes un POST con cuerpo JSON { id, type, created_at, tenant, data } y estas cabeceras:

  • X-VoiceOps-Event: tipo de evento.
  • X-VoiceOps-Event-Id: identificador único; úsalo para ser idempotente (un reintento lleva el mismo).
  • X-VoiceOps-Signature: t=<segundos>,v1=<hex>, donde v1 es el HMAC-SHA256 de "{t}.{cuerpo}" con tu secreto.

Responde con un 2xx en menos de 10 segundos. Si no, se reintenta a 1 min, 5 min, 30 min, 2 h y 12 h. Tras 10 eventos sin entregar el webhook se desactiva. Solo se admiten direcciones https públicas y no se siguen redirecciones.

// Node.js: verificar la firma
import crypto from 'node:crypto';
function verify(rawBody, header, secret) {
  const [t, v1] = header.split(',').map((p) => p.split('=')[1]);
  if (Math.abs(Date.now() / 1000 - Number(t)) > 300) return false;       // rechaza peticiones antiguas
  const expected = crypto.createHmac('sha256', secret).update(t + '.' + rawBody).digest('hex');
  return crypto.timingSafeEqual(Buffer.from(v1), Buffer.from(expected));
}

Eventos

call.startedEmpieza una llamada (entrante o saliente)
call.answeredSe atiende la llamada
call.completedTermina con normalidad
call.failedNo se completa (fallo, sin respuesta, rechazada)
transcript.completedResumen e intención listos
agent.transferredEl agente transfiere a una persona
appointment.createdSe crea una cita
appointment.cancelledSe cancela una cita
automation.executedTermina la ejecución de un flujo