Key Takeways
- Cada Integración de API OTP se reduce a dos puntos finales REST: enviar (devuelve el ID de verificación) y validar (acepta el ID y el código, devuelve el estado verificado).
- La integración con calidad de producción gestiona 5 categorías de error específicas: número no válido, código no coincidente, caducado, velocidad limitada y detección de fraude.
- Usa webhooks para el estado de entrega asincrónico en lugar de sondear, y verifica siempre el encabezado de la firma.
- Lista de verificación de producción de 12 elementos antes de voltear la bandera de las funciones: secrets, libphonenumber, SMS Retriever, WebTop, menú desplegable de países, temporizador de reenvío, respaldo multicanal, webhooks firmados, alertas, límites de velocidad a nivel de aplicación, manejo de STOP, runbook.
- Elige el idioma en el que está escrito tu servicio de autenticación: REST es REST, los SDK son en su mayoría cosméticos.
Si eres un desarrollador que evalúa un API OTP para una aplicación dirigida a EE. UU. en 2026, no quieres otra página de marketing, quieres un código que funcione. Esta guía es un tutorial práctico sobre la integración de un API de verificación de números de teléfono en una aplicación de producción: referencia de puntos finales de REST, ejemplos de código de trabajo en Node.js, Python, PHP y Java, gestión de errores, gestión de webhooks, pruebas de sandbox y una lista de verificación de producción antes de cambiar el indicador de función.
Todos los ejemplos usan los puntos finales REST de VerifyNow, pero los patrones se transfieren a la mayoría API OTP modernas (Twilio Verify, Vonage Verify, Sinch Verify) con cambios mínimos. Cuando surjan dudas específicas de EE. UU. (enrutamiento con 10 DLC, suscripción mediante TCPA, protección contra el fraude), las comunicaremos en línea.
Los dos puntos finales que necesita
Cada flujo de verificación OTP se reduce a dos llamadas REST, independientemente del proveedor:
- POST /verificación/envío: genera una OTP, elige el canal óptimo (SMS, WhatsApp, voz) y envía el código al teléfono del usuario. Devuelve un identificador de verificación para la próxima llamada.
- PUBLICAR/verificación/validación: acepta el identificador de verificación y el código que ha introducido el usuario. Devuelve el éxito o el fracaso más un código de error en caso de error.
Todo lo demás (preferencias de canal, políticas de reintento, opciones de protección contra el fraude) es la configuración del envío de la llamada. La mayoría de los proveedores exponen entre 8 y 12 parámetros opcionales; los valores predeterminados son razonables en aproximadamente el 80% de los casos de uso.
Node.js: Enviar y verificar OTP
//Instalar: npm install axios
const axios = require ('axios');
const API_BASE = 'https://cpaas.messagecentral.com/verification/v3';
const API_KEY = process.env.MC_API_KEY;
función asíncrona SendOTP (número de teléfono, canal = 'SMS') {
const response = await axios.post (`$ {API_BASE} /send`, {
Código de país: '1',
Número de móvil: número de teléfono,
flowType: canal,//'SMS' | 'WHATSAPP' | 'VOZ'
Longitud máxima: 6,6
}, {
encabezados: {'authToken': API_KEY}
});
devuelve response.data.data.verificationId;
}
función asíncrona VerifyOtp (VerificationId, código) {
const response = await axios.post (`$ {API_BASE} /validate`, {
ID de verificación,
código,
}, {
encabezados: {'authToken': API_KEY}
});
return response.data.data.VerificationStatus === 'VERIFICADO';
}
//Uso en tu flujo de autenticación
const VerificationId = wait SendOp ('5551234567');
//... el usuario introduce el código...
const verificado = wait VerifyOTP (VerificationId, '482917');
Python: enviar y verificar OTP
# Instalación: solicitudes de instalación de pip
sistema operativo de importación
solicitudes de importación
API_BASE = 'https://cpaas.messagecentral.com/verification/v3'
API_KEY = os.environ ['MC_API_KEY']
def send_otp (número_teléfono, canal = 'SMS'):
respuesta = requests.post (
f' {API_BASE} /enviar»,
json = {
'Código de país': '1',
'Número móvil': número_teléfono,
'flowType': canal,
«Longitud máxima»: 6,
},
headers= {'authToken': API_KEY}
)
response.raise_for_status ()
return response.json () ['datos'] ['VerificationID']
def verify_otp (identificación_de_verificación, código):
respuesta = requests.post (
f' {API_BASE} /validar»,
json = {
'VerificationID': verification_id,
'código': código,
},
headers= {'authToken': API_KEY}
)
response.raise_for_status ()
return response.json () ['data'] ['VerificationStatus'] == 'VERIFICADO'
PHP: Enviar y verificar OTP
<? php
//Uso de cURL: no se necesitan dependencias externas.
define ('API_BASE', 'https://cpaas.messagecentral.com/verification/v3');
define ('API_KEY', getenv ('MC_API_KEY'));
función SendOTP ($número de teléfono, $canal = 'SMS') {
$ch = curl_init (API_BASE). '/enviar');
curl_setopt_array ($ch, [
CURLOPT_RETURNTRANSFER => verdadero,
CURLOPT_POST => verdadero,
CURLOPT_HTTPHEADER => [
'AuthToken: '. API_KEY,
'Tipo de contenido: aplicación/json',
],
CURLOPT_POSTFIELDS => json_encode ([
'countryCode' => '1',
'mobileNumber' => $número de teléfono,
'flowType' => $canal,
'Longitud máxima' => 6,
]),
]);
$respuesta = json_decode (curl_exec ($ch), verdadero);
curl_close ($ch);
devuelve $response ['data'] ['verificationId'];
}
función verifyOtp ($verificationId, $code) {
$ch = curl_init (API_BASE). '/validar');
curl_setopt_array ($ch, [
CURLOPT_RETURNTRANSFER => verdadero,
CURLOPT_POST => verdadero,
CURLOPT_HTTPHEADER => [
'AuthToken: '. API_KEY,
'Tipo de contenido: aplicación/json',
],
CURLOPT_POSTFIELDS => json_encode ([
'VerificationId' => $verificationID,
'código' => $código,
]),
]);
$respuesta = json_decode (curl_exec ($ch), verdadero);
curl_close ($ch);
return $response ['data'] ['VerificationStatus'] === 'VERIFICADO';
}
Java: enviar y verificar OTP
//Uso de java.net.http (JDK 11+).
importar java.net.URI;
importar java.net.http.HttpClient;
importar java.net.http.HttpRequest;
importar java.net.http.HttpResponse;
importar com.fasterxml.jackson.databind.ObjectMapper;
importar com.fasterXml.jackson.databind.jsonNode;
clase pública VerifyNowClient {
cadena final estática privada API_BASE = "https://cpaas.messagecentral.com/verification/v3 «;
cadena final estática privada API_KEY = System.getEnv («MC_API_KEY»);
cliente HttpClient final estático privado = HttpClient.newHttpClient ();
mapeador ObjectMapper final estático privado = new ObjectMapper ();
La cadena estática pública SendOTP (String phoneNumber, String channel) arroja una excepción {
Cuerpo de la cadena = mapper.writeValueAsString (java.util.map.of (
«Código de país», «1",
«Número de móvil», número de teléfono,
«FlowType», canal,
«Longitud máxima», 6
));
HttpRequest req = HttpRequest.newBuilder ()
.uri (URI.create (API_BASE + «/enviar»))
.header («AuthToken», API_KEY)
.header («Tipo de contenido», «aplicación/json»)
.POST (http://Request.bodyPublishers.ofString (body))
.construir ();
HttpResponse <String>resp = client.send (req, HttpResponse.bodyHandlers.ofString ());
return Mapper.readTree (resp.body ()) .get («data») .get («VerificationId») .asText ();
}
El booleano estático público VerifyOtp (String VerificationId, String code) arroja la excepción {
Cuerpo de la cadena = mapper.writeValueAsString (java.util.map.of (
«ID de verificación», ID de verificación,
«código», código
));
HttpRequest req = HttpRequest.newBuilder ()
.uri (URI.create (API_BASE + «/validar»))
.header («AuthToken», API_KEY)
.header («Tipo de contenido», «aplicación/json»)
.POST (http://Request.bodyPublishers.ofString (body))
.construir ();
HttpResponse <String>resp = client.send (req, HttpResponse.bodyHandlers.ofString ());
devuelve «VERIFICADO» .equals (mapper.readTree (resp.body ())
.get («datos») .get («Estado de verificación») .asText ());
}
}
Manejo de errores que realmente necesita
Los errores que importan en la producción no son los que van en el buen camino. Hay cinco que debes manejar:
Formato de número de teléfono no válido
Devuelve HTTP 400 con código de error NÚMERO_INVÁLIDO. Usa los de Google número de teléfono libphone para normalizar antes de llamar a la API.
Discordancia de código
El usuario ha introducido una OTP incorrecta. Devuelve HTTP 200 con Estado de verificación: «FALLIDO». Permita entre 3 y 5 intentos antes de invalidar el ID de verificación.
Código caducado
El usuario esperó demasiado. Devoluciones Estado de verificación: «CADUCADO». Muestra una CTA de «reenvío de código» en tu interfaz de usuario.
Tarifa limitada
El mismo número de teléfono solicitó demasiadas OTP. Devuelve HTTP 429. No lo vuelva a intentar de inmediato; retroceda exponencialmente.
Bombeo de SMS detectado
Devuelve HTTP 403 con código de error FRAUD_DETECTADO. No vuelvas a intentarlo. Marca la solicitud en tu canal de detección de fraudes.
Webhooks para el estado de entrega
Para las implementaciones de producción, escuche las llamadas de entrega asincrónicas en lugar de las encuestas. Configure una URL de webhook en el panel de control de su proveedor y, a continuación, gestione:
//Ejemplo de controlador de webhooks de Express.js
app.post ('/webhooks/verifynow', (req, res) => {
const {VerificationId, deliveryStatus, channel, latencyMS} = req.body;
//Persistir para el análisis
db.DeliveryEvents.insert ({
ID de verificación,
DeliveryStatus,//'ENTREGADO' | 'FALLIDO' | 'PENDIENTE'
canal,//'SMS' | 'WHATSAPP' | 'VOZ'
Latencia MS,
marca de tiempo: nueva fecha (),
});
//Opcional: active el respaldo a un canal alternativo en caso de error
if (DeliveryStatus === 'FALLIDO' && canal === 'SMS') {
SendOTPFallback (ID de verificación, 'WHATSAPP');
}
res.status (200) .end ();
});
Verifique siempre la autenticidad de los webhooks utilizando el encabezado de firma que envía su proveedor; nunca confíe en un webhook sin firmar en producción.
Pruebas en sandbox antes de la producción
Antes de voltear el indicador de función, valida de principio a fin en la zona de pruebas:
- Números de teléfono de prueba: la mayoría Proveedores OTP en EE. UU. ofrecen números de prueba reservados que siempre tienen éxito, fracaso o tiempo de espera de forma determinista.
- Pruebas de red: verifique que su firewall permita el HTTPS saliente a los puntos finales de la API del proveedor (normalmente el puerto 443).
- Pruebas de límite de velocidad: active deliberadamente un límite de frecuencia por número y confirme que su gestión de errores muestra un mensaje útil.
- Pruebas de latencia: mide el tiempo de ida y vuelta para el envío y compruébalo con una carga normal.
- Pruebas de entrega de webhooks: usa un servicio como webhook.site para inspeccionar las devoluciones de llamadas antes de dirigirlas a la producción.
El entorno de pruebas de VerifyNow utiliza créditos de prueba gratuitos sin tarjeta de crédito, por lo que puedes ejecutar la integración completa en preproducción sin comprometerte con un contrato.
Lista de verificación de producción antes del lanzamiento
Doce elementos que hay que verificar antes de cambiar el indicador de función:
- Claves de API almacenadas en el administrador de secretos (no en el control de código fuente)
- libphonenumber instalado y usado para la normalización del lado del cliente
- API de recuperación de SMS integrada en Android (omite la entrada manual de códigos)
- API WebTop integrada en la web (autocompletar a partir de la notificación)
- El menú desplegable de códigos de país se establece de forma predeterminada en la dirección geográfica del usuario
- El botón «Reenviar código» está oculto durante los primeros 30 segundos y luego se revela
- Alternativa multicanal habilitada (SMS → WhatsApp → Voz)
- El controlador de webhook autentica el encabezado de la firma
- Alerta de entrega fallida transferida a Slack/PagerDuty
- Límite de velocidad por IP y por número en su capa de aplicación (no solo en la del proveedor)
- Probado el manejo de palabras clave Stop (conformidad con TCPA)
- Redacción y almacenamiento del manual de producción para escenarios en los que la entrega OTP no funciona
Preguntas frecuentes
¿Qué idioma tiene el mejor SDK para las API OTP?
La mayoría de los proveedores ofrecen SDK oficiales en Node, Python, Java, PHP, Go y Ruby con paridad de funciones. Las diferencias entre los SDK son en su mayoría estéticas: REST es REST. Elige el idioma en el que tu equipo escribe el servicio de autenticación. Si tu equipo escribe en Rust o .NET, es sencillo llamar a los puntos finales REST directamente con el cliente HTTP del idioma (como en el ejemplo de Java anterior).
¿Cómo puedo gestionar el respaldo de OTP a un canal diferente en caso de error?
Dos patrones: (a) configurar el respaldo automático del lado del proveedor enumerando los canales por orden de prioridad en la llamada de envío, y el proveedor intenta cada uno de ellos en secuencia si se produce un error en la entrega; (b) escucha los webhooks de entrega y activa una nueva llamada de envío con un canal diferente al de tu aplicación. La primera es más sencilla; la segunda te da más control. Verificar ahora admite ambos patrones.
¿Debo implementar la interfaz de usuario OTP en la web con WebOTP?
Sí, cuando los navegadores lo admitan. API WebTop de Google rellena automáticamente el código de una notificación por SMS en Chrome y Edge. El mensaje OTP debe tener un formato especial (por ejemplo, «Tu código es 123456 #abc .example.com #482917 «) para que los navegadores lo reconozcan. Vuelve sin problemas a la introducción manual en navegadores no compatibles.
Obtenga una clave de Sandbox en menos de un minuto
La forma más rápida de validar cualquiera de los códigos anteriores es ejecutarlo en un sandbox real. VerifyNow para EE. UU. le ofrece créditos de prueba gratuitos sin tarjeta de crédito, terminales REST documentados de principio a fin y SDK en 6 idiomas. La mayoría de los equipos lanzan su primera integración de OTP a las pocas horas de registrarse.

.svg%20(1).png)



