Migración de Twilio a Prelude

Blog /

Código OTP

De Twilio a Prelude: Guía Técnica de Migración

Guía técnica paso a paso: migra de Twilio Messaging y Twilio Verify a la API de Verify de Prelude. Sencillo, robusto y eficiente.

Quentin Le Bras

Dirección de Producto

Síntesis

Prelude unifica todo el ciclo de tus OTP en una sola API, con detección de fraude por ML y ruteo multicanal inteligente. Esta guía te muestra la equivalencia directa desde Twilio para autenticar, enviar y verificar códigos, gestionar reintentos y configurar tus webhooks de forma simple.

Reemplazar tu proveedor de OTP no tiene por qué ser un proyecto de varios sprints. La API unificada Verify de Prelude se adapta directamente a los conceptos de Twilio Verify. Prelude ofrece un único endpoint REST que gestiona todo el ciclo de vida de las OTP, desde la detección de fraude hasta el enrutamiento multicanal. La mayoría de los equipos implementan un reemplazo funcional en un solo sprint.

¿Por qué migrar? Las empresas que cambian a Prelude suelen registrar tasas de conversión entre un 20 y un 30% más altas y costes mensuales de SMS entre un 30 y un 40% menores, además de contar con prevención de fraude integrada basada en ML que no requiere herramientas personalizadas.

Qué cambia

A grandes rasgos, vas a sustituir dos entornos de Twilio (Programmable Messaging y Twilio Verify) por una única API de Prelude. La siguiente tabla asocia cada concepto de Twilio con su equivalente en Prelude.

Concepto

Twilio Verify

Prelude Verify

Categoría de servicio

Twilio Programmable Messaging + Twilio Verify

API de Prelude Verify (servicio único)

URL base de la API

api.twilio.com/2010-04-01/Accounts/{SID}

api.prelude.dev

Autenticación

HTTP Básica (AccountSID:AuthToken)

Token Bearer en cabecera Authorization

Enviar OTP

POST /Services/{ServiceSID}/Verifications

POST /v2/verification

Verificar OTP

POST /Services/{ServiceSID}/VerificationChecks

POST /v2/verification/check

Reintentar OTP

POST /Services/{ServiceSID}/Verifications (repetir)

POST /v2/verification (mismo número, dentro del intervalo)

Estado de verificación

pending / approved / canceled

success / retry / blocked / challenged

Servicio / espacio de nombres

Servicio Verify (ServiceSID)

Implícito por clave de API (configurado en el Dashboard)

Prevención de fraude

Twilio Fraud Guard (complemento)

ML integrado, activo por defecto

Canales

SMS, WhatsApp, llamada, email

SMS, WhatsApp, Viber, Zalo, RCS, voz, email

Remitente / marca

Servicio de mensajería o número de teléfono

Configurado contactando con Customer Success (Sender ID)

Números de prueba

Números mágicos por Servicio Verify

Números de prueba en el Dashboard (Verify > Configure > Numbers)

Webhooks

URL StatusCallback por petición

callback_url por petición; firma mediante RSASSA-PSS

SDKs

twilio-node, twilio-python, etc.

npm @prelude.so/sdk, pip prelude_python_sdk, go-sdk, Java, Ruby

Autenticación

Twilio (antes)

Twilio utiliza autenticación HTTP básica con tu SID de cuenta como usuario y tu token de autenticación como contraseña.

# Twilio HTTP Basic Auth

curl -X POST https://verify.twilio.com/v2/Services/{ServiceSID}/Verifications \

  -u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN \

  -d 'To=+14155552671' \

  -d 'Channel=sms'
# Twilio HTTP Basic Auth

curl -X POST https://verify.twilio.com/v2/Services/{ServiceSID}/Verifications \

  -u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN \

  -d 'To=+14155552671' \

  -d 'Channel=sms'

Prelude (después)

Prelude utiliza un token Bearer. Genera una clave de API en el Dashboard, dentro de Settings > API Keys.

# Prelude Bearer Token

curl -X POST https://api.prelude.dev/v2/verification \

  -H “Authorization: Bearer $PRELUDE_API_KEY” \

  -H 'Content-Type: application/json' \

  -d '{"target": {"type": "phone_number", "value": "+14155552671"}}'
# Prelude Bearer Token

curl -X POST https://api.prelude.dev/v2/verification \

  -H “Authorization: Bearer $PRELUDE_API_KEY” \

  -H 'Content-Type: application/json' \

  -d '{"target": {"type": "phone_number", "value": "+14155552671"}}'

Acción requerida: Almacena tu clave de API de Prelude en una variable de entorno (por ejemplo, PRELUDE_API_KEY). Nunca la subas al control de código fuente. Elimina TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN y VERIFY_SERVICE_SID una vez completada la migración.

Enviar una verificación (OTP)

Twilio Verify – antes

// Node.js – Twilio Verify

const client = require('twilio')(accountSid, authToken);



const verification = await client.verify.v2

  .services(verifySid)

  .verifications

  .create({ to: '+14155552671', channel: 'sms' });



console.log(verification.status); // 'pending'
// Node.js – Twilio Verify

const client = require('twilio')(accountSid, authToken);



const verification = await client.verify.v2

  .services(verifySid)

  .verifications

  .create({ to: '+14155552671', channel: 'sms' });



console.log(verification.status); // 'pending'

Prelude – después

// Node.js – Prelude SDK

import Prelude from '@prelude.so/sdk';



const client = new Prelude({ apiToken: process.env.PRELUDE_API_KEY });



const verification = await client.verification.create({

  target: { type: 'phone_number', value: '+14155552671' },

  // Opcional: envía señales digitales para combatir mejor el fraude

  signals: {

    ip: '203.0.113.42',          // IP pública del usuario final

    device_id: 'abc123-unique',   // identificador único y estable del dispositivo

    device_platform: 'ios',

    device_model: 'iPhone 15',

  },

});



console.log(verification.id);     // 'vrf_01...'

console.log(verification.status); // 'success' | 'blocked' | 'challenged'
// Node.js – Prelude SDK

import Prelude from '@prelude.so/sdk';



const client = new Prelude({ apiToken: process.env.PRELUDE_API_KEY });



const verification = await client.verification.create({

  target: { type: 'phone_number', value: '+14155552671' },

  // Opcional: envía señales digitales para combatir mejor el fraude

  signals: {

    ip: '203.0.113.42',          // IP pública del usuario final

    device_id: 'abc123-unique',   // identificador único y estable del dispositivo

    device_platform: 'ios',

    device_model: 'iPhone 15',

  },

});



console.log(verification.id);     // 'vrf_01...'

console.log(verification.status); // 'success' | 'blocked' | 'challenged'

Valores de estado

Prelude devuelve un conjunto de estados más completo al crear una verificación:

Estado

Significado

success

Intervalo de verificación abierto; código enviado al usuario.

retry

Se ha vuelto a solicitar el mismo número dentro del intervalo; nuevo intento enviado.

blocked

Petición marcada como fraudulenta; no se envía código ni se cobra por el mensaje.

challenged

Tráfico sospechoso; entrega restringida únicamente a canales que no sean SMS (debe activarlo el soporte de Prelude).

Verificar un código de verificación

Twilio Verify – antes

// Node.js – Twilio Verify check

const check = await client.verify.v2

  .services(verifySid)

  .verificationChecks

  .create({ to: '+14155552671', code: '123456' });




if (check.status === 'approved') {

  // dar acceso

}
// Node.js – Twilio Verify check

const check = await client.verify.v2

  .services(verifySid)

  .verificationChecks

  .create({ to: '+14155552671', code: '123456' });




if (check.status === 'approved') {

  // dar acceso

}

Prelude – después

// Node.js – Prelude check

const check = await client.verification.check({

  target: { type: 'phone_number', value: '+14155552671' },

  code: '123456',

});




if (check.status === 'success') {

  // dar acceso

}




// Posibles estados: 'success' | 'failure' | ‘expired_or_not_found’
// Node.js – Prelude check

const check = await client.verification.check({

  target: { type: 'phone_number', value: '+14155552671' },

  code: '123456',

});




if (check.status === 'success') {

  // dar acceso

}




// Posibles estados: 'success' | 'failure' | ‘expired_or_not_found’

Gestión de reintentos

En Twilio Verify inicias un reintento creando una nueva verificación para el mismo número dentro del intervalo de reintento del servicio. Prelude funciona exactamente igual: llama de nuevo a POST /v2/verification con el mismo número y Prelude identificará el intervalo de verificación abierto, generando un nuevo intento en lugar de una verificación desde cero.

// Prelude – reintento (misma llamada que create)

const retry = await client.verification.create({

  target: { type: 'phone_number', value: '+14155552671' },

});




// retry.status === 'retry' cuando está dentro del intervalo

// Devuelve 429 Too Many Requests si se alcanza el máximo de intentos

// o si se llama antes del retraso mínimo entre reintentos
// Prelude – reintento (misma llamada que create)

const retry = await client.verification.create({

  target: { type: 'phone_number', value: '+14155552671' },

});




// retry.status === 'retry' cuando está dentro del intervalo

// Devuelve 429 Too Many Requests si se alcanza el máximo de intentos

// o si se llama antes del retraso mínimo entre reintentos

Puedes configurar el número máximo de intentos y la duración del intervalo de verificación desde el Dashboard de Prelude.

Prevención de fraude

Twilio Fraud Guard frente a la prevención integrada de Prelude

Twilio Fraud Guard es un complemento opcional. La prevención de fraude de Prelude está activada por defecto en cada petición, respaldada por modelos de ML y heurísticas entrenadas con decenas de millones de datos en toda la red de Prelude.

Señales recomendadas

Cuantas más señales proporciones, más efectiva será la detección del fraude. La tabla muestra la mejora estimada de conversión según la señal:

Campo de señal

Mejora estimada • Notas

signals.ip

+50%  •  IPv4 o IPv6 pública del dispositivo del usuario final. Si usa proxy, emplea X-Forwarded-For / CF-Connecting-IP.

signals.device_id

+40%  •  ID único y estable por dispositivo (Android: ANDROID_ID, iOS: identifierForVendor).

signals.device_platform

+35%  •  'ios' o 'android'.

signals.ja4_fingerprint

+30%  •  Autodetectado al usar los SDKs de Frontend de Prelude; envíalo manualmente si terminas la conexión TLS.

signals.device_model

+20%  •  Modelo del dispositivo.

signals.os_version

+20%  •  Versión del sistema operativo.

signals.app_version

+10%  •  Versión de tu aplicación.

Uso de SDKs de Frontend para señales más ricas y huella de red

Instala uno de los SDKs de Frontend de Prelude (Android, iOS, Web, React Native, Flutter) para recopilar señales del dispositivo automáticamente. El SDK captura estos datos y te proporciona un dispatch_id que luego envías a la llamada de verificación en el backend.

// Ejemplo de SDK Web – obtener dispatch_id en el frontend

import { dispatchSignals } from "@prelude.so/js-sdk/signals";




const dispatchId = await dispatchSignals(<tu-clave-sdk-prelude>);




// Backend – enviar dispatch_id para asociar las señales del dispositivo

const verification = await client.verification.create({

target: { type

// Ejemplo de SDK Web – obtener dispatch_id en el frontend

import { dispatchSignals } from "@prelude.so/js-sdk/signals";




const dispatchId = await dispatchSignals(<tu-clave-sdk-prelude>);




// Backend – enviar dispatch_id para asociar las señales del dispositivo

const verification = await client.verification.create({

target: { type

Canales y enrutamiento inteligente

Twilio Verify te obliga a especificar un canal ('sms', 'whatsapp', 'call', 'email') explícitamente. Prelude elige automáticamente el mejor canal y ruta según el coste, la conversión y las señales de fraude, evitándote tener que gestionar esa lógica.

No requiere acción:  Elimina el campo de canal de tus payloads. El motor de enrutamiento inteligente de Prelude decide el canal de forma automática. Aún puedes configurar canales preferidos desde el Dashboard si lo necesitas.

Contenido del mensaje y personalización

Prelude envía la OTP con el siguiente formato:

12345 es tu código de verificación.

El mensaje se traduce automáticamente a 32 idiomas según el prefijo del país del número de teléfono. Opciones de personalización disponibles (configurables en el Dashboard o por petición):

  • Sufijo de marca – ej. “12345 es tu código de verificación para {nombre_empresa}.”

  • Sufijo de seguridad – ej. “No lo compartas.”

  • Idioma personalizado – mediante options.locale (formato BCP-47).

  • Longitud del código – de 4 a 8 dígitos definido en el Dashboard, anulable con options.code_size.

  • Código OTP propio – define tu propio código con options.custom_code (sujeto a aprobación).

  • Plantilla PSD2 – plantilla integrada para transacciones PSD2 mediante options.template_id: 'prelude:psd2'.

Webhooks

Twilio – antes

Twilio envía un POST de StatusCallback a la URL que indiques en el Servicio Verify o por petición.

Prelude – después

Define una callback_url para cada petición de verificación.

const verification = await client.verification.create({

  target: {

    type: 'phone_number',

    value: '+14155552671',

  },

  options: {

    callback_url: 'https://your-app.example.com/webhooks/prelude',

  },

});
const verification = await client.verification.create({

  target: {

    type: 'phone_number',

    value: '+14155552671',

  },

  options: {

    callback_url: 'https://your-app.example.com/webhooks/prelude',

  },

});

Tipos de evento

Tipo de evento

Descripción

verify.authentication

Se ha creado y facturado una verificación.

verify.attempt

Se ha enviado un intento de OTP al usuario.

verify.delivery_status

Actualización del estado de entrega recibida del operador.

Verificación de firmas

Prelude firma cada webhook con RSASSA-PSS sobre el hash SHA-256 del payload. La firma se incluye en la cabecera X-Webhook-Signature, precedida por rsassa-pss-sha256=. Genera tu clave de firma en el Dashboard.

Lista de IPs permitidas

Añade estas IPs de salida de Prelude en las reglas de tu firewall:

  • 34.252.67.209

  • 52.30.192.161

  • 34.248.153.151

Probar tu integración

Números mágicos de Twilio frente a números de prueba de Prelude

Ambas plataformas ofrecen números especiales sin coste para pruebas automatizadas. En Prelude, se configuran en el Dashboard dentro de Verify API > Configure > Numbers.

Para cada número de prueba defines un código fijo. Solo ese código será aceptado por el endpoint Check, facilitando la creación de flujos de prueba (éxito/fallo) en tu pipeline.

Buena práctica: Usa números de prueba en tus flujos de CI/CD. Añádelos al Dashboard antes de ejecutar tus tests de integración.

Instalación e inicialización del SDK

Node.js

# Remove Twilio

npm uninstall twilio




# Install Prelude

npm add @prelude.so/sdk
# Remove Twilio

npm uninstall twilio




# Install Prelude

npm add @prelude.so/sdk
import Prelude from '@prelude.so/sdk';




const client = new Prelude({

  apiToken: process.env.PRELUDE_API_KEY,

});
import Prelude from '@prelude.so/sdk';




const client = new Prelude({

  apiToken: process.env.PRELUDE_API_KEY,

});

Python

# Remove Twilio

pip uninstall twilio




# Install Prelude

pip install prelude_python_sdk
# Remove Twilio

pip uninstall twilio




# Install Prelude

pip install prelude_python_sdk
from prelude_python_sdk import Prelude

import os




client = Prelude(api_token=os.environ['PRELUDE_API_KEY'])
from prelude_python_sdk import Prelude

import os




client = Prelude(api_token=os.environ['PRELUDE_API_KEY'])

Go

go get github.com/prelude-so/go-sdk
go get github.com/prelude-so/go-sdk
import (

  "github.com/prelude-so/go-sdk"

  "github.com/prelude-so/go-sdk/option"




client := prelude.NewClient(

  option.WithAPIToken(os.Getenv("PRELUDE_API_KEY")),

)
import (

  "github.com/prelude-so/go-sdk"

  "github.com/prelude-so/go-sdk/option"




client := prelude.NewClient(

  option.WithAPIToken(os.Getenv("PRELUDE_API_KEY")),

)

Java / Kotlin

// build.gradle

implementation("so.prelude.sdk:prelude-java:0.2.0")




// Initialise

PreludeClient client = PreludeOkHttpClient.fromEnv();

// Set API_TOKEN environment variable
// build.gradle

implementation("so.prelude.sdk:prelude-java:0.2.0")




// Initialise

PreludeClient client = PreludeOkHttpClient.fromEnv();

// Set API_TOKEN environment variable

Ruby

# Gemfile

gem 'prelude_sdk'




# Initialise

require 'prelude_sdk'

prelude = PreludeSDK::Client.new(api_token: ENV['API_TOKEN'])
# Gemfile

gem 'prelude_sdk'




# Initialise

require 'prelude_sdk'

prelude = PreludeSDK::Client.new(api_token: ENV['API_TOKEN'])

Lista de control para la migración

Sigue estos pasos para completar con éxito tu migración:

Fase 1 – Configuración

  • Crea una cuenta de Prelude en app.prelude.so e inicia sesión en el Dashboard.

  • Genera una clave de API en Dashboard > Configure > API Keys.

  • Añade PRELUDE_API_KEY a tu gestor de secretos o variables de entorno.

  • Instala el SDK de Prelude correspondiente a tu lenguaje de programación (ver Sección 12).

  • Configura los números de prueba en Dashboard > Verify API > Configure > Numbers.

Fase 2 – Cambios en el código

  • Sustituye la inicialización del SDK de Twilio por el de Prelude (ver Sección 12).

  • Cambia verifications.create(...) por client.verification.create(...).

  • Cambia verificationChecks.create(...) por client.verification.check(...).

  • Actualiza las comprobaciones de estado de 'approved' a 'success' y de 'pending' a 'success'.

  • Elimina el parámetro channel: Prelude selecciona el canal idóneo automáticamente.

  • Elimina las referencias a ServiceSID.

  • Añade señales de fraude (signals.ip, signals.device_id, etc.) en las llamadas de creación de verificación.

  • Actualiza la lógica del webhook para procesar los eventos de Prelude (ver Sección 10.3).

  • Implementa la verificación de firma en tus webhooks (RSASSA-PSS, ver Sección 10.4).

Fase 3 – Pruebas

  • Realiza una prueba completa end-to-end en tu entorno de staging con un número de teléfono real.

  • Verifica que los webhooks se reciban y procesen correctamente.

  • Confirma que los escenarios bloqueados o con sospecha de fraude devuelven el estado esperado.

Fase 4 – Despliegue progresivo

  • Despliega en producción (se aconseja usar un feature flag o canary).

  • Monitorea las tasas de conversión y bloqueo directamente en el Dashboard de Prelude.

  • Elimina definitivamente las credenciales antiguas de Twilio de tu gestor de secretos.

Guía rápida de códigos de error

Prelude utiliza códigos de estado HTTP estándar. La respuesta contiene un objeto JSON con los campos de código y descripción.

Código / Estado HTTP

Descripción

429 too_many_attempts

Se ha alcanzado el límite máximo de reintentos para este intervalo de verificación.

429 premature_retry

Reintento solicitado antes de que se cumpla el retraso mínimo requerido.

429 too_many_checks

Se ha alcanzado el límite de intentos de validación del código.

400 invalid_phone_number

El número de teléfono no cumple con el formato válido E.164.

401 unauthorized

Clave de API inválida o ausente.

Ver el catálogo completo de errores de tipo 4xx

https://docs.prelude.so/introduction/errors

Recursos y soporte

¿Por qué deberíamos migrar de Twilio a Prelude?

Existen cuatro razones principales para dar el paso:

  • Costes más bajos. La reducción del gasto mensual en SMS ronda el 30-40%. Esto es gracias a que el sistema de prevención de fraude de Prelude intercepta el tráfico sospechoso antes de enviarlo a los operadores: no pagas por mensajes fraudulentos.

  • Mayor conversión. El enrutamiento inteligente selecciona de forma automática la mejor vía para cada entrega. Las tasas de conversión de OTP suelen aumentar entre un 20 y un 30%.

  • Seguridad antifraude integrada. A diferencia de Twilio, donde Fraud Guard es un añadido de pago, el motor basado en ML de Prelude viene activo por defecto en cada petición, respaldado por millones de interacciones analizadas.

  • Integración simplificada. Unifica dos servicios de Twilio (Messaging y Verify) en una única API minimalista. Olvídate de los ServiceSID, del enrutamiento manual y de los proveedores de red.

El cambio conlleva un riesgo mínimo: la estructura de Prelude es totalmente equivalente a la de Twilio Verify. La mayoría de integradores completan el despliegue funcional en un sprint mediante un lanzamiento escalonado. Conoce cómo Finfrog redujo sus costes un 45%: Caso de estudio de Finfrog

Estamos cómodos con Twilio. ¿Vale la pena el cambio?

La inversión en desarrollo es muy baja; habitualmente bastan unos pocos días de ingeniería, por lo que cualquier pequeña mejora en conversión o costes compensa rápido. Migrar es especialmente clave si:

  • Sufres ataques de fraude o abuso por SMS en tu registro.

  • La entrega de tus OTP fluctúa según el país o el operador.

  • Estás pagando un extra por el filtro antifraude de Twilio.

  • Quieres enviar OTPs por WhatsApp, Viber o RCS sin complicar tu infraestructura.

Puedes comprobar los resultados sin riesgos usando un despliegue canary: desvía entre el 5 y el 10% de tu tráfico a Prelude y evalúa la conversión frente a tu sistema actual en tiempo real. Finfrog hizo exactamente esto para migrar por completo en tiempo récord: lee el caso de estudio

¿Cuánto tiempo requiere la migración?

Casi todos los equipos backend completan la migración en un único sprint. Los cambios esenciales (sustituir el SDK, adaptar las llamadas de envío/comprobación y mapear estados) toman solo unas horas. Integrar las firmas de webhooks y enviar las señales de los dispositivos puede dejarse como una mejora incremental posterior.

¿Es posible usar Twilio y Prelude en paralelo durante un despliegue gradual?

Por supuesto, de hecho es nuestra recomendación. Encapsula la llamada bajo un feature flag para desviar primero un pequeño porcentaje del tráfico. Controla los resultados en tu panel de control de Prelude y aumenta el flujo progresivamente. Mantén activas tus credenciales de Twilio hasta que la migración sea total.

¿La protección contra el fraude funciona por defecto o debo activarla?

Sí, está activa por defecto. No necesitas configurar nada para disfrutar de la protección básica desde el primer día. Enviar datos contextuales (como ip, device_id o device_platform) sirve para maximizar la efectividad de los modelos de detección de fraude en tiempo real.

¿Existe un panel de control en tiempo real para monitorizar la entrega y los bloqueos?

Sí. El Dashboard de Prelude ofrece total visibilidad sobre tus tasas de entrega, bloqueos y canales activos. Monitoriza estas métricas durante la fase de despliegue para validar el rendimiento antes de desactivar tu integración anterior.

Reemplazar tu proveedor de OTP no tiene por qué ser un proyecto de varios sprints. La API unificada Verify de Prelude se adapta directamente a los conceptos de Twilio Verify. Prelude ofrece un único endpoint REST que gestiona todo el ciclo de vida de las OTP, desde la detección de fraude hasta el enrutamiento multicanal. La mayoría de los equipos implementan un reemplazo funcional en un solo sprint.

¿Por qué migrar? Las empresas que cambian a Prelude suelen registrar tasas de conversión entre un 20 y un 30% más altas y costes mensuales de SMS entre un 30 y un 40% menores, además de contar con prevención de fraude integrada basada en ML que no requiere herramientas personalizadas.

Qué cambia

A grandes rasgos, vas a sustituir dos entornos de Twilio (Programmable Messaging y Twilio Verify) por una única API de Prelude. La siguiente tabla asocia cada concepto de Twilio con su equivalente en Prelude.

Concepto

Twilio Verify

Prelude Verify

Categoría de servicio

Twilio Programmable Messaging + Twilio Verify

API de Prelude Verify (servicio único)

URL base de la API

api.twilio.com/2010-04-01/Accounts/{SID}

api.prelude.dev

Autenticación

HTTP Básica (AccountSID:AuthToken)

Token Bearer en cabecera Authorization

Enviar OTP

POST /Services/{ServiceSID}/Verifications

POST /v2/verification

Verificar OTP

POST /Services/{ServiceSID}/VerificationChecks

POST /v2/verification/check

Reintentar OTP

POST /Services/{ServiceSID}/Verifications (repetir)

POST /v2/verification (mismo número, dentro del intervalo)

Estado de verificación

pending / approved / canceled

success / retry / blocked / challenged

Servicio / espacio de nombres

Servicio Verify (ServiceSID)

Implícito por clave de API (configurado en el Dashboard)

Prevención de fraude

Twilio Fraud Guard (complemento)

ML integrado, activo por defecto

Canales

SMS, WhatsApp, llamada, email

SMS, WhatsApp, Viber, Zalo, RCS, voz, email

Remitente / marca

Servicio de mensajería o número de teléfono

Configurado contactando con Customer Success (Sender ID)

Números de prueba

Números mágicos por Servicio Verify

Números de prueba en el Dashboard (Verify > Configure > Numbers)

Webhooks

URL StatusCallback por petición

callback_url por petición; firma mediante RSASSA-PSS

SDKs

twilio-node, twilio-python, etc.

npm @prelude.so/sdk, pip prelude_python_sdk, go-sdk, Java, Ruby

Autenticación

Twilio (antes)

Twilio utiliza autenticación HTTP básica con tu SID de cuenta como usuario y tu token de autenticación como contraseña.

# Twilio HTTP Basic Auth

curl -X POST https://verify.twilio.com/v2/Services/{ServiceSID}/Verifications \

  -u $TWILIO_ACCOUNT_SID:$TWILIO_AUTH_TOKEN \

  -d 'To=+14155552671' \

  -d 'Channel=sms'

Prelude (después)

Prelude utiliza un token Bearer. Genera una clave de API en el Dashboard, dentro de Settings > API Keys.

# Prelude Bearer Token

curl -X POST https://api.prelude.dev/v2/verification \

  -H “Authorization: Bearer $PRELUDE_API_KEY” \

  -H 'Content-Type: application/json' \

  -d '{"target": {"type": "phone_number", "value": "+14155552671"}}'

Acción requerida: Almacena tu clave de API de Prelude en una variable de entorno (por ejemplo, PRELUDE_API_KEY). Nunca la subas al control de código fuente. Elimina TWILIO_ACCOUNT_SID, TWILIO_AUTH_TOKEN y VERIFY_SERVICE_SID una vez completada la migración.

Enviar una verificación (OTP)

Twilio Verify – antes

// Node.js – Twilio Verify

const client = require('twilio')(accountSid, authToken);



const verification = await client.verify.v2

  .services(verifySid)

  .verifications

  .create({ to: '+14155552671', channel: 'sms' });



console.log(verification.status); // 'pending'

Prelude – después

// Node.js – Prelude SDK

import Prelude from '@prelude.so/sdk';



const client = new Prelude({ apiToken: process.env.PRELUDE_API_KEY });



const verification = await client.verification.create({

  target: { type: 'phone_number', value: '+14155552671' },

  // Opcional: envía señales digitales para combatir mejor el fraude

  signals: {

    ip: '203.0.113.42',          // IP pública del usuario final

    device_id: 'abc123-unique',   // identificador único y estable del dispositivo

    device_platform: 'ios',

    device_model: 'iPhone 15',

  },

});



console.log(verification.id);     // 'vrf_01...'

console.log(verification.status); // 'success' | 'blocked' | 'challenged'

Valores de estado

Prelude devuelve un conjunto de estados más completo al crear una verificación:

Estado

Significado

success

Intervalo de verificación abierto; código enviado al usuario.

retry

Se ha vuelto a solicitar el mismo número dentro del intervalo; nuevo intento enviado.

blocked

Petición marcada como fraudulenta; no se envía código ni se cobra por el mensaje.

challenged

Tráfico sospechoso; entrega restringida únicamente a canales que no sean SMS (debe activarlo el soporte de Prelude).

Verificar un código de verificación

Twilio Verify – antes

// Node.js – Twilio Verify check

const check = await client.verify.v2

  .services(verifySid)

  .verificationChecks

  .create({ to: '+14155552671', code: '123456' });




if (check.status === 'approved') {

  // dar acceso

}

Prelude – después

// Node.js – Prelude check

const check = await client.verification.check({

  target: { type: 'phone_number', value: '+14155552671' },

  code: '123456',

});




if (check.status === 'success') {

  // dar acceso

}




// Posibles estados: 'success' | 'failure' | ‘expired_or_not_found’

Gestión de reintentos

En Twilio Verify inicias un reintento creando una nueva verificación para el mismo número dentro del intervalo de reintento del servicio. Prelude funciona exactamente igual: llama de nuevo a POST /v2/verification con el mismo número y Prelude identificará el intervalo de verificación abierto, generando un nuevo intento en lugar de una verificación desde cero.

// Prelude – reintento (misma llamada que create)

const retry = await client.verification.create({

  target: { type: 'phone_number', value: '+14155552671' },

});




// retry.status === 'retry' cuando está dentro del intervalo

// Devuelve 429 Too Many Requests si se alcanza el máximo de intentos

// o si se llama antes del retraso mínimo entre reintentos

Puedes configurar el número máximo de intentos y la duración del intervalo de verificación desde el Dashboard de Prelude.

Prevención de fraude

Twilio Fraud Guard frente a la prevención integrada de Prelude

Twilio Fraud Guard es un complemento opcional. La prevención de fraude de Prelude está activada por defecto en cada petición, respaldada por modelos de ML y heurísticas entrenadas con decenas de millones de datos en toda la red de Prelude.

Señales recomendadas

Cuantas más señales proporciones, más efectiva será la detección del fraude. La tabla muestra la mejora estimada de conversión según la señal:

Campo de señal

Mejora estimada • Notas

signals.ip

+50%  •  IPv4 o IPv6 pública del dispositivo del usuario final. Si usa proxy, emplea X-Forwarded-For / CF-Connecting-IP.

signals.device_id

+40%  •  ID único y estable por dispositivo (Android: ANDROID_ID, iOS: identifierForVendor).

signals.device_platform

+35%  •  'ios' o 'android'.

signals.ja4_fingerprint

+30%  •  Autodetectado al usar los SDKs de Frontend de Prelude; envíalo manualmente si terminas la conexión TLS.

signals.device_model

+20%  •  Modelo del dispositivo.

signals.os_version

+20%  •  Versión del sistema operativo.

signals.app_version

+10%  •  Versión de tu aplicación.

Uso de SDKs de Frontend para señales más ricas y huella de red

Instala uno de los SDKs de Frontend de Prelude (Android, iOS, Web, React Native, Flutter) para recopilar señales del dispositivo automáticamente. El SDK captura estos datos y te proporciona un dispatch_id que luego envías a la llamada de verificación en el backend.

// Ejemplo de SDK Web – obtener dispatch_id en el frontend

import { dispatchSignals } from "@prelude.so/js-sdk/signals";




const dispatchId = await dispatchSignals(<tu-clave-sdk-prelude>);




// Backend – enviar dispatch_id para asociar las señales del dispositivo

const verification = await client.verification.create({

target: { type

Canales y enrutamiento inteligente

Twilio Verify te obliga a especificar un canal ('sms', 'whatsapp', 'call', 'email') explícitamente. Prelude elige automáticamente el mejor canal y ruta según el coste, la conversión y las señales de fraude, evitándote tener que gestionar esa lógica.

No requiere acción:  Elimina el campo de canal de tus payloads. El motor de enrutamiento inteligente de Prelude decide el canal de forma automática. Aún puedes configurar canales preferidos desde el Dashboard si lo necesitas.

Contenido del mensaje y personalización

Prelude envía la OTP con el siguiente formato:

12345 es tu código de verificación.

El mensaje se traduce automáticamente a 32 idiomas según el prefijo del país del número de teléfono. Opciones de personalización disponibles (configurables en el Dashboard o por petición):

  • Sufijo de marca – ej. “12345 es tu código de verificación para {nombre_empresa}.”

  • Sufijo de seguridad – ej. “No lo compartas.”

  • Idioma personalizado – mediante options.locale (formato BCP-47).

  • Longitud del código – de 4 a 8 dígitos definido en el Dashboard, anulable con options.code_size.

  • Código OTP propio – define tu propio código con options.custom_code (sujeto a aprobación).

  • Plantilla PSD2 – plantilla integrada para transacciones PSD2 mediante options.template_id: 'prelude:psd2'.

Webhooks

Twilio – antes

Twilio envía un POST de StatusCallback a la URL que indiques en el Servicio Verify o por petición.

Prelude – después

Define una callback_url para cada petición de verificación.

const verification = await client.verification.create({

  target: {

    type: 'phone_number',

    value: '+14155552671',

  },

  options: {

    callback_url: 'https://your-app.example.com/webhooks/prelude',

  },

});

Tipos de evento

Tipo de evento

Descripción

verify.authentication

Se ha creado y facturado una verificación.

verify.attempt

Se ha enviado un intento de OTP al usuario.

verify.delivery_status

Actualización del estado de entrega recibida del operador.

Verificación de firmas

Prelude firma cada webhook con RSASSA-PSS sobre el hash SHA-256 del payload. La firma se incluye en la cabecera X-Webhook-Signature, precedida por rsassa-pss-sha256=. Genera tu clave de firma en el Dashboard.

Lista de IPs permitidas

Añade estas IPs de salida de Prelude en las reglas de tu firewall:

  • 34.252.67.209

  • 52.30.192.161

  • 34.248.153.151

Probar tu integración

Números mágicos de Twilio frente a números de prueba de Prelude

Ambas plataformas ofrecen números especiales sin coste para pruebas automatizadas. En Prelude, se configuran en el Dashboard dentro de Verify API > Configure > Numbers.

Para cada número de prueba defines un código fijo. Solo ese código será aceptado por el endpoint Check, facilitando la creación de flujos de prueba (éxito/fallo) en tu pipeline.

Buena práctica: Usa números de prueba en tus flujos de CI/CD. Añádelos al Dashboard antes de ejecutar tus tests de integración.

Instalación e inicialización del SDK

Node.js

# Remove Twilio

npm uninstall twilio




# Install Prelude

npm add @prelude.so/sdk
import Prelude from '@prelude.so/sdk';




const client = new Prelude({

  apiToken: process.env.PRELUDE_API_KEY,

});

Python

# Remove Twilio

pip uninstall twilio




# Install Prelude

pip install prelude_python_sdk
from prelude_python_sdk import Prelude

import os




client = Prelude(api_token=os.environ['PRELUDE_API_KEY'])

Go

go get github.com/prelude-so/go-sdk
import (

  "github.com/prelude-so/go-sdk"

  "github.com/prelude-so/go-sdk/option"




client := prelude.NewClient(

  option.WithAPIToken(os.Getenv("PRELUDE_API_KEY")),

)

Java / Kotlin

// build.gradle

implementation("so.prelude.sdk:prelude-java:0.2.0")




// Initialise

PreludeClient client = PreludeOkHttpClient.fromEnv();

// Set API_TOKEN environment variable

Ruby

# Gemfile

gem 'prelude_sdk'




# Initialise

require 'prelude_sdk'

prelude = PreludeSDK::Client.new(api_token: ENV['API_TOKEN'])

Lista de control para la migración

Sigue estos pasos para completar con éxito tu migración:

Fase 1 – Configuración

  • Crea una cuenta de Prelude en app.prelude.so e inicia sesión en el Dashboard.

  • Genera una clave de API en Dashboard > Configure > API Keys.

  • Añade PRELUDE_API_KEY a tu gestor de secretos o variables de entorno.

  • Instala el SDK de Prelude correspondiente a tu lenguaje de programación (ver Sección 12).

  • Configura los números de prueba en Dashboard > Verify API > Configure > Numbers.

Fase 2 – Cambios en el código

  • Sustituye la inicialización del SDK de Twilio por el de Prelude (ver Sección 12).

  • Cambia verifications.create(...) por client.verification.create(...).

  • Cambia verificationChecks.create(...) por client.verification.check(...).

  • Actualiza las comprobaciones de estado de 'approved' a 'success' y de 'pending' a 'success'.

  • Elimina el parámetro channel: Prelude selecciona el canal idóneo automáticamente.

  • Elimina las referencias a ServiceSID.

  • Añade señales de fraude (signals.ip, signals.device_id, etc.) en las llamadas de creación de verificación.

  • Actualiza la lógica del webhook para procesar los eventos de Prelude (ver Sección 10.3).

  • Implementa la verificación de firma en tus webhooks (RSASSA-PSS, ver Sección 10.4).

Fase 3 – Pruebas

  • Realiza una prueba completa end-to-end en tu entorno de staging con un número de teléfono real.

  • Verifica que los webhooks se reciban y procesen correctamente.

  • Confirma que los escenarios bloqueados o con sospecha de fraude devuelven el estado esperado.

Fase 4 – Despliegue progresivo

  • Despliega en producción (se aconseja usar un feature flag o canary).

  • Monitorea las tasas de conversión y bloqueo directamente en el Dashboard de Prelude.

  • Elimina definitivamente las credenciales antiguas de Twilio de tu gestor de secretos.

Guía rápida de códigos de error

Prelude utiliza códigos de estado HTTP estándar. La respuesta contiene un objeto JSON con los campos de código y descripción.

Código / Estado HTTP

Descripción

429 too_many_attempts

Se ha alcanzado el límite máximo de reintentos para este intervalo de verificación.

429 premature_retry

Reintento solicitado antes de que se cumpla el retraso mínimo requerido.

429 too_many_checks

Se ha alcanzado el límite de intentos de validación del código.

400 invalid_phone_number

El número de teléfono no cumple con el formato válido E.164.

401 unauthorized

Clave de API inválida o ausente.

Ver el catálogo completo de errores de tipo 4xx

https://docs.prelude.so/introduction/errors

Recursos y soporte

¿Por qué deberíamos migrar de Twilio a Prelude?

Existen cuatro razones principales para dar el paso:

  • Costes más bajos. La reducción del gasto mensual en SMS ronda el 30-40%. Esto es gracias a que el sistema de prevención de fraude de Prelude intercepta el tráfico sospechoso antes de enviarlo a los operadores: no pagas por mensajes fraudulentos.

  • Mayor conversión. El enrutamiento inteligente selecciona de forma automática la mejor vía para cada entrega. Las tasas de conversión de OTP suelen aumentar entre un 20 y un 30%.

  • Seguridad antifraude integrada. A diferencia de Twilio, donde Fraud Guard es un añadido de pago, el motor basado en ML de Prelude viene activo por defecto en cada petición, respaldado por millones de interacciones analizadas.

  • Integración simplificada. Unifica dos servicios de Twilio (Messaging y Verify) en una única API minimalista. Olvídate de los ServiceSID, del enrutamiento manual y de los proveedores de red.

El cambio conlleva un riesgo mínimo: la estructura de Prelude es totalmente equivalente a la de Twilio Verify. La mayoría de integradores completan el despliegue funcional en un sprint mediante un lanzamiento escalonado. Conoce cómo Finfrog redujo sus costes un 45%: Caso de estudio de Finfrog

Estamos cómodos con Twilio. ¿Vale la pena el cambio?

La inversión en desarrollo es muy baja; habitualmente bastan unos pocos días de ingeniería, por lo que cualquier pequeña mejora en conversión o costes compensa rápido. Migrar es especialmente clave si:

  • Sufres ataques de fraude o abuso por SMS en tu registro.

  • La entrega de tus OTP fluctúa según el país o el operador.

  • Estás pagando un extra por el filtro antifraude de Twilio.

  • Quieres enviar OTPs por WhatsApp, Viber o RCS sin complicar tu infraestructura.

Puedes comprobar los resultados sin riesgos usando un despliegue canary: desvía entre el 5 y el 10% de tu tráfico a Prelude y evalúa la conversión frente a tu sistema actual en tiempo real. Finfrog hizo exactamente esto para migrar por completo en tiempo récord: lee el caso de estudio

¿Cuánto tiempo requiere la migración?

Casi todos los equipos backend completan la migración en un único sprint. Los cambios esenciales (sustituir el SDK, adaptar las llamadas de envío/comprobación y mapear estados) toman solo unas horas. Integrar las firmas de webhooks y enviar las señales de los dispositivos puede dejarse como una mejora incremental posterior.

¿Es posible usar Twilio y Prelude en paralelo durante un despliegue gradual?

Por supuesto, de hecho es nuestra recomendación. Encapsula la llamada bajo un feature flag para desviar primero un pequeño porcentaje del tráfico. Controla los resultados en tu panel de control de Prelude y aumenta el flujo progresivamente. Mantén activas tus credenciales de Twilio hasta que la migración sea total.

¿La protección contra el fraude funciona por defecto o debo activarla?

Sí, está activa por defecto. No necesitas configurar nada para disfrutar de la protección básica desde el primer día. Enviar datos contextuales (como ip, device_id o device_platform) sirve para maximizar la efectividad de los modelos de detección de fraude en tiempo real.

¿Existe un panel de control en tiempo real para monitorizar la entrega y los bloqueos?

Sí. El Dashboard de Prelude ofrece total visibilidad sobre tus tasas de entrega, bloqueos y canales activos. Monitoriza estas métricas durante la fase de despliegue para validar el rendimiento antes de desactivar tu integración anterior.

Optimiza tu flujo de autenticación ahora

Envía SMS de verificación a todo el mundo: al mejor precio, con entrega garantizada y sin spam.