Enviar Código de Verificación (OTP)
channel: el mismo código sale por el canal nuevo y cubres los números que no reciben SMS. La respuesta siempre te dice qué hizo (action) y qué sigue (next)./v2/otpPara probar, basta con phone_number, country_code, company y message; el código llega por SMS en segundos. Con code_in_response: true la respuesta incluye el código y puedes automatizar la prueba sin leer el teléfono.
Cuerpo de la solicitud
application/json
52.Canal de entrega del código:
sms(default): mensaje de texto.whatsapp: mensaje de WhatsApp oficial con plantilla fija (ignoramessageycompany). No requiere cuenta de WhatsApp Business ni verificación de Meta: sale por nuestra integración oficial (remitenteAuthenticate).voice: llamada que dicta el código dígito por dígito.
En un reenvío puedes cambiar de canal: el mismo código pendiente sale por el canal nuevo (fallback).
Nombre de tu empresa o app. Se inserta en message mediante el placeholder {{company}}.
Si channel es whatsapp, se ignora: la plantilla oficial de WhatsApp es fija (recibes un warning avisando).
Texto que recibe el usuario. Debe incluir los placeholders {{code}} y {{company}}, usar solo caracteres GSM-7 (sin emojis ni acentos raros) y no exceder 160 caracteres ya con el código y la empresa sustituidos.
Ejemplo armado (con code: "483920" y company: "Mi Empresa"): 483920 es tu codigo de verificacion de Mi Empresa. No lo compartas.
Si channel es whatsapp, se ignora: el texto sale por la plantilla oficial fija de WhatsApp (recibes un warning avisando).
Formato del código generado:
numeric(default): solo números.alphanumeric: letras y números.letters: solo letras.
true descarta el código vigente y genera uno nuevo (nueva ronda con 7 intentos). Sin él, un código vigente se reenvía tal cual. El cooldown de 30s aplica igual.Devuelve el código generado en el campo code de la respuesta:
false(default): no devolver.true: devolver (pruebas/automatización del lado del servidor).
true el flujo se ejecuta completo (genera y registra el código) pero el SMS no se entrega y no se descuenta saldo. Como el usuario nunca recibe el mensaje, debes enviar también code_in_response: true para obtener el código en la respuesta; si falta, responde 400 otp_missing_param.YYYY-MM-DD HH:mm:ss (futura). Por defecto 24 horas; máximo 3 días (si envías más, se ajusta al máximo).Respuesta
action: resent) o rotado sobre una ronda en curso (action: restarted)pending: hay un código activo esperando verificación.Qué hizo la API con tu solicitud:
created: primera verificación para el número (o la anterior ya había expirado). HTTP201.resent: reenvió el mismo código vigente. HTTP200.restarted: generó un código nuevo e inició otra ronda (concode_rotate: true, o tras una verificación completada). HTTP200o201.
YYYY-MM-DD HH:mm:ss, hora del centro de México).message/company con channel: whatsapp (se ignoran, la plantilla de WhatsApp es fija).code_in_response: true (pruebas/automatización).pending: hay un código activo esperando verificación.Qué hizo la API con tu solicitud:
created: primera verificación para el número (o la anterior ya había expirado). HTTP201.resent: reenvió el mismo código vigente. HTTP200.restarted: generó un código nuevo e inició otra ronda (concode_rotate: true, o tras una verificación completada). HTTP200o201.
YYYY-MM-DD HH:mm:ss, hora del centro de México).message/company con channel: whatsapp (se ignoran, la plantilla de WhatsApp es fija).code_in_response: true (pruebas/automatización).otp_missing_param, otp_invalid_param, otp_invalid_channel, otp_message_invalid)Slug estable del error, para manejo programático:
| Slug | HTTP | Significado |
|---|---|---|
otp_missing_param |
400 |
Falta un parámetro obligatorio. |
otp_invalid_param |
400 |
Un parámetro es inválido o no aplica a este endpoint. |
otp_invalid_channel |
400 |
channel debe ser sms, whatsapp o voice. |
otp_message_invalid |
400 |
El message personalizado no cumple las reglas (placeholders, GSM-7, 160). |
otp_incorrect_code |
401 |
El código no coincide. |
otp_insufficient_credits |
402 |
Saldo insuficiente para enviar. |
otp_not_found |
404 |
No hay verificación activa para el número. |
otp_already_verified |
409 |
El número ya está verificado. |
otp_code_expired |
410 |
El código expiró. |
otp_throttled |
429 |
Cooldown de reenvío activo (espera resend_available_in). |
otp_max_attempts |
429 |
Se agotaron los 7 intentos de verificación de la ronda. |
otp_internal |
500 |
Error inesperado. |
otp_send_failed |
502 |
El mensaje no pudo enviarse. |
otp_throttled).otp_insufficient_credits: siempre sms_07, el código estándar de saldo insuficiente de toda la API.Slug estable del error, para manejo programático:
| Slug | HTTP | Significado |
|---|---|---|
otp_missing_param |
400 |
Falta un parámetro obligatorio. |
otp_invalid_param |
400 |
Un parámetro es inválido o no aplica a este endpoint. |
otp_invalid_channel |
400 |
channel debe ser sms, whatsapp o voice. |
otp_message_invalid |
400 |
El message personalizado no cumple las reglas (placeholders, GSM-7, 160). |
otp_incorrect_code |
401 |
El código no coincide. |
otp_insufficient_credits |
402 |
Saldo insuficiente para enviar. |
otp_not_found |
404 |
No hay verificación activa para el número. |
otp_already_verified |
409 |
El número ya está verificado. |
otp_code_expired |
410 |
El código expiró. |
otp_throttled |
429 |
Cooldown de reenvío activo (espera resend_available_in). |
otp_max_attempts |
429 |
Se agotaron los 7 intentos de verificación de la ronda. |
otp_internal |
500 |
Error inesperado. |
otp_send_failed |
502 |
El mensaje no pudo enviarse. |
otp_throttled).otp_insufficient_credits: siempre sms_07, el código estándar de saldo insuficiente de toda la API.otp_throttled) o intentos de verificación agotados sin code_rotate (otp_max_attempts). Incluye header Retry-After.Slug estable del error, para manejo programático:
| Slug | HTTP | Significado |
|---|---|---|
otp_missing_param |
400 |
Falta un parámetro obligatorio. |
otp_invalid_param |
400 |
Un parámetro es inválido o no aplica a este endpoint. |
otp_invalid_channel |
400 |
channel debe ser sms, whatsapp o voice. |
otp_message_invalid |
400 |
El message personalizado no cumple las reglas (placeholders, GSM-7, 160). |
otp_incorrect_code |
401 |
El código no coincide. |
otp_insufficient_credits |
402 |
Saldo insuficiente para enviar. |
otp_not_found |
404 |
No hay verificación activa para el número. |
otp_already_verified |
409 |
El número ya está verificado. |
otp_code_expired |
410 |
El código expiró. |
otp_throttled |
429 |
Cooldown de reenvío activo (espera resend_available_in). |
otp_max_attempts |
429 |
Se agotaron los 7 intentos de verificación de la ronda. |
otp_internal |
500 |
Error inesperado. |
otp_send_failed |
502 |
El mensaje no pudo enviarse. |
otp_throttled).otp_insufficient_credits: siempre sms_07, el código estándar de saldo insuficiente de toda la API.Slug estable del error, para manejo programático:
| Slug | HTTP | Significado |
|---|---|---|
otp_missing_param |
400 |
Falta un parámetro obligatorio. |
otp_invalid_param |
400 |
Un parámetro es inválido o no aplica a este endpoint. |
otp_invalid_channel |
400 |
channel debe ser sms, whatsapp o voice. |
otp_message_invalid |
400 |
El message personalizado no cumple las reglas (placeholders, GSM-7, 160). |
otp_incorrect_code |
401 |
El código no coincide. |
otp_insufficient_credits |
402 |
Saldo insuficiente para enviar. |
otp_not_found |
404 |
No hay verificación activa para el número. |
otp_already_verified |
409 |
El número ya está verificado. |
otp_code_expired |
410 |
El código expiró. |
otp_throttled |
429 |
Cooldown de reenvío activo (espera resend_available_in). |
otp_max_attempts |
429 |
Se agotaron los 7 intentos de verificación de la ronda. |
otp_internal |
500 |
Error inesperado. |
otp_send_failed |
502 |
El mensaje no pudo enviarse. |
otp_throttled).otp_insufficient_credits: siempre sms_07, el código estándar de saldo insuficiente de toda la API.Slug estable del error, para manejo programático:
| Slug | HTTP | Significado |
|---|---|---|
otp_missing_param |
400 |
Falta un parámetro obligatorio. |
otp_invalid_param |
400 |
Un parámetro es inválido o no aplica a este endpoint. |
otp_invalid_channel |
400 |
channel debe ser sms, whatsapp o voice. |
otp_message_invalid |
400 |
El message personalizado no cumple las reglas (placeholders, GSM-7, 160). |
otp_incorrect_code |
401 |
El código no coincide. |
otp_insufficient_credits |
402 |
Saldo insuficiente para enviar. |
otp_not_found |
404 |
No hay verificación activa para el número. |
otp_already_verified |
409 |
El número ya está verificado. |
otp_code_expired |
410 |
El código expiró. |
otp_throttled |
429 |
Cooldown de reenvío activo (espera resend_available_in). |
otp_max_attempts |
429 |
Se agotaron los 7 intentos de verificación de la ronda. |
otp_internal |
500 |
Error inesperado. |
otp_send_failed |
502 |
El mensaje no pudo enviarse. |
otp_throttled).otp_insufficient_credits: siempre sms_07, el código estándar de saldo insuficiente de toda la API.Qué hace cada llamada
El endpoint decide según el estado del número; tú solo repites el POST:
| Estado del número | Qué hace | HTTP | action |
|---|---|---|---|
| Sin verificación activa (o expirada) | Crea y envía un código nuevo. | 201 | created |
| Código vigente | Reenvía el mismo código. | 200 | resent |
Código vigente + code_rotate: true | Descarta el anterior y genera uno nuevo (7 intentos frescos). | 200 | restarted |
| Ya verificado | Inicia un ciclo nuevo. | 201 | restarted |
Entre envíos aplica un cooldown de 30 segundos (con o sin code_rotate); si no esperas, recibes 429 otp_throttled con el tiempo restante.
Dependencias entre parámetros
companyymessageson obligatorios en toda petición, sin importar el canal — mándalos siempre igual y solo cambiachannel.messagedebe incluir{{code}}y{{company}}.channel: whatsappreemplazacompanyymessagepor su plantilla oficial fija (recibes unwarningavisando que se ignoraron); ensmsyvoicese usan tal cual los envías.sandbox: true(modo prueba: no entrega el SMS ni descuenta saldo) requierecode_in_response: true; sin él,400 otp_missing_param.
code_in_response: true está pensado para pruebas y automatización del lado del servidor. Nunca reenvíes esa respuesta al navegador o a la app del usuario: si el código regresa al mismo cliente que lo va a capturar, el flujo deja de probar la posesión del teléfono.
Cómo leer los errores
Cada error llega con su status HTTP real, un slug estable en error, una sugerencia accionable en hint y los endpoints sugeridos en next:
| HTTP | error | Cuándo ocurre | Qué hacer |
|---|---|---|---|
400 | otp_missing_param / otp_invalid_param | Falta un parámetro, es inválido, o enviaste uno de la API anterior (voice, whatsapp, template). | El hint indica el parámetro exacto. |
400 | otp_invalid_channel | channel no es sms, whatsapp ni voice. | Corrige el valor. |
400 | otp_message_invalid | message sin {{code}}/{{company}}, con caracteres fuera de GSM-7, o que excede 160 caracteres ya expandido. | El hint detalla la regla incumplida. |
402 | otp_insufficient_credits | Sin saldo para enviar (incluye code: sms_07). | Recarga saldo. |
429 | otp_throttled | Cooldown de reenvío activo. | Espera resend_available_in segundos (también en el header Retry-After). |
429 | otp_max_attempts | La ronda está bloqueada por intentos agotados y no enviaste code_rotate. | Rota el código con code_rotate: true. |
502 | otp_send_failed | El canal no pudo entregar el mensaje. | Reintenta; si persiste, contacta a soporte con el request_id. |
Los errores de autenticación (auth_*) vienen de la capa común de la API y llegan con HTTP 200 y el detalle en el body; consulta Errores y límites.