Voice API v2

Documentación técnica

Todo lo que necesitás para integrar VerityFone en tu producto. Guías, referencia completa de endpoints y ejemplos de código en 6 lenguajes.

SDKs oficiales disponibles para Node.js, Python, PHP, Go, Ruby y .NET. Todos con soporte completo para la API v2, retry automático, y verificación Ed25519 nativa.

Quickstart · Primera llamada en 5 minutos

Este ejemplo dispara una verificación 2FA por voz al número de destino. El destinatario escucha un audio, marca 6 dígitos en su teclado, y VerityFone envía un webhook con el resultado.

1. Instalá el SDK

Node.js
Python
PHP
Go
Copiar
# npm
npm install verityfone

# yarn
yarn add verityfone

# pnpm
pnpm add verityfone

2. Autenticá con tu API key

Node.js
Copiar
import VerityFone from 'verityfone';

const client = new VerityFone({
  apiKey: process.env.VERITYFONE_API_KEY,
  timeout: 30000,
  maxRetries: 3,
});

3. Realizá tu primera llamada

Node.js
Copiar
const call = await client.calls.create({
  to: '+51987654321',
  from: '+13025550134',
  webhookUrl: 'https://tu-app.com/callback',
  gather: {
    digits: 6,
    timeoutSecs: 30,
    audioUrl: 'https://cdn.tu-app.com/otp-es.mp3',
  },
});

console.log(call.id);         // call_2xR8wNfP...
console.log(call.status);     // 'queued'
El endpoint POST /v2/calls responde en <100ms p50. La llamada se procesa asíncrona · recibís eventos vía webhook (call.answered, call.gather.ended, call.hangup, call.cost).

Autenticación

VerityFone usa Bearer authentication con API keys. Todas las requests deben incluir tu API key en el header Authorization.

HTTP
Copiar
Authorization: Bearer VF_LIVE_a4b2c9d8f1e6...

Podés crear y rotar API keys desde el dashboard en /settings/api-keys. Recomendamos:

  • Una API key por ambiente (VF_LIVE_* producción · VF_TEST_* testing)
  • Rotación cada 90 días
  • IP allowlist para keys de producción (opcional)
  • Scopes granulares para keys de CI/CD
Nunca expongas tu API key en frontend. Todas las llamadas a la API deben hacerse desde tu servidor. Si necesitás integración cliente-side, usá Ephemeral Tokens.

SDKs oficiales

Mantenemos SDKs en 6 lenguajes principales. Todos incluyen retry automático con exponential backoff, verificación de firma Ed25519 nativa, y tipos TypeScript/mypy/PHPDoc completos.

LenguajePackageRepoVersión
Node.js · TypeScriptverityfonegithub.com/verityfone/node3.2.1
Python 3.9+verityfonegithub.com/verityfone/python2.4.0
PHP 8.1+verityfone/verityfone-phpgithub.com/verityfone/php2.1.3
Go 1.20+github.com/verityfone/gogithub.com/verityfone/go1.8.2
Ruby 3.0+verityfonegithub.com/verityfone/ruby1.5.0
.NET 6+VerityFone.SDKgithub.com/verityfone/dotnet1.3.4

Crear una llamada

POST/v2/calls

Inicia una nueva llamada saliente. La llamada se procesa asíncrona · el response contiene el call.id que podés usar para consultar estado o ejecutar acciones.

Parámetros del body

CampoTipoDescripción
to *stringNúmero destino en formato E.164 · +51987654321
from *stringUno de tus números VerityFone · +13025550134
webhook_url *stringURL HTTPS que recibirá eventos de esta llamada
gatherobjectConfiguración de recolección DTMF · ver abajo
timeout_secsintegerSegundos máximos de ring · default 30 · máx 60
machine_detectionstringnone · detect · hangup_on_machine
recordbooleanGrabar la llamada · default false (compliance)
client_statestringBase64 · datos propios que se devuelven en webhooks · máx 512 chars
caller_display_namestringNombre CNAM que aparece en el teléfono destino (US only)

Campos con * son requeridos.

Ejemplo request completo

curl
Node.js
Python
PHP
Copiar
curl -X POST https://api.verityfone.com/v2/calls \
  -H "Authorization: Bearer VF_LIVE_a4b2c9d8f1e6..." \
  -H "Content-Type: application/json" \
  -d '{
    "to": "+51987654321",
    "from": "+13025550134",
    "webhook_url": "https://tu-app.com/callback",
    "gather": {
      "digits": 6,
      "timeout_secs": 30,
      "audio_url": "https://cdn.tu-app.com/otp-es.mp3",
      "invalid_audio_url": "https://cdn.tu-app.com/invalid-es.mp3",
      "retry": 2
    },
    "machine_detection": "hangup_on_machine",
    "client_state": "eyJvcmRlcl9pZCI6IjEyMzQ1In0="
  }'

Response · 201 Created

JSON
Copiar
{
  "data": {
    "id": "call_2xR8wNfPqLk9mYzT4Bv3wCsD",
    "object": "call",
    "status": "queued",
    "to": "+51987654321",
    "from": "+13025550134",
    "created_at": "2026-08-18T14:23:45.123Z",
    "webhook_url": "https://tu-app.com/callback",
    "estimated_cost": "0.0245",
    "currency": "USD"
  },
  "request_id": "req_5nHqM3xW9pKzT2LvBcRs"
}

Verificación de firma Ed25519

Todos los webhooks de VerityFone se firman con Ed25519. Debés verificar la firma antes de procesar el evento para evitar spoofing.

La firma llega en el header VerityFone-Signature junto con VerityFone-Timestamp. El payload firmado es {timestamp}.{raw_body}.

Node.js
Copiar
import nacl from 'tweetnacl';

function verifySignature(rawBody, signature, timestamp, publicKey) {
  // 1. Verificar timestamp (previene replay attacks)
  const age = Math.abs(Date.now() / 1000 - parseInt(timestamp));
  if (age > 300) throw new Error('Timestamp too old');

  // 2. Verificar firma
  const signed = Buffer.from(`${timestamp}.${rawBody}`);
  const sig    = Buffer.from(signature, 'base64');
  const key    = Buffer.from(publicKey, 'base64');

  return nacl.sign.detached.verify(signed, sig, key);
}
Rechazá cualquier webhook cuya firma no verifique. Los SDKs oficiales manejan esto automáticamente · si implementás manualmente, usá comparación constant-time para evitar timing attacks.

Eventos de webhook

VerityFone emite estos eventos durante el ciclo de vida de una llamada:

EventoDescripción
call.initiatedLa llamada fue aceptada por VerityFone y encolada
call.ringingEl teléfono destino está sonando
call.answeredEl destinatario contestó · empezá gather aquí
call.gather.endedEl destinatario ingresó DTMF o expiró timeout
call.playback.startedEmpezó a reproducirse un audio
call.playback.endedTerminó de reproducirse un audio
call.machine.detectionResultado de detección de contestador (si activado)
call.hangupLa llamada terminó (por vos, por destino, por timeout)
call.costLlega ~1-3s post-hangup con el costo real

Códigos de error

La API usa códigos HTTP estándar. El body de errores 4xx/5xx tiene esta estructura:

JSON
Copiar
{
  "error": {
    "code": "invalid_number",
    "message": "El número destino no está en formato E.164",
    "param": "to",
    "docs_url": "https://verityfone.com/documentacion/errors#invalid_number"
  },
  "request_id": "req_5nHqM3xW9pKzT2LvBcRs"
}
Código HTTPSignificado
200 · 201Éxito
400Request malformada · revisá param en el error
401API key inválida o faltante
402Saldo insuficiente en tu cuenta
403Sin permisos para ese recurso · revisá scopes de la API key
404Recurso no existe · verificá el ID
409Conflicto · recurso ya existe o estado incompatible
422Validación fallida · destino en blocklist / prefix bloqueado
429Rate limit excedido · esperá Retry-After segundos
500Error interno · reintentá con exponential backoff
503Mantenimiento programado · ver estado

Rate limits

Los límites son por API key y se resetean cada 60 segundos. Todos los responses incluyen headers X-RateLimit-*.

PlanRequests/minLlamadas concurrentes
Inicial6020
Empresa600200
Corporativo6,0002,000
CustomPersonalizadoPersonalizado
Al llegar al rate limit recibís HTTP 429 con header Retry-After. Los SDKs oficiales respetan este header y reintentan automáticamente con exponential backoff.

Changelog

Últimos cambios de la API:

  • 2026-08-15 · Nuevo campo machine_detection.model · algoritmo v3 con 12% mejor precisión
  • 2026-08-01 · Endpoint /v2/numbers/available ahora filtra por área code
  • 2026-07-20 · Firma Ed25519 rotada · nueva public key en portal
  • 2026-07-10 · Soporte para números toll-free en 15 nuevos países
  • 2026-06-25 · gather.retry ahora acepta hasta 5 (antes 3)

Ver changelog completo →

¿Necesitás ayuda? Escribinos a soporte@verityfone.com · respondemos en < 4 horas hábiles. Los clientes Empresa+ tienen soporte 24/7.