OTP y verificación de móvil por SMS para programadores con IA
Mete la verificación por SMS en cualquier proyecto desde Claude Code, Cursor, Windsurf o llamando HTTP a pelo. Los códigos salen por tu Android emparejado, la comparación corre en tiempo constante, y un tope de 5 por número al día corta el abuso antes de que empiece.
Dos endpoints, una ida y vuelta
La misma lógica tanto si quien llama es un asistente de IA por MCP, un cliente externo por HTTPS, o tu propio backend.
send_otp
Genera el código, guarda el hash con caducidad y contador de intentos, y dispara el SMS por tu Android emparejado.
El usuario lo lee
El cliente recibe el SMS en su móvil y teclea el código en tu formulario.
verify_otp
Compara en tiempo constante con el último código emitido. Devuelve verified y los intentos restantes si falla.
Solo POST, autenticación Bearer
Los GET devuelven 405. Las cookies se ignoran. La clave de API nunca acaba en una URL ni en el historial del navegador.
Endpoint de envío
POST https://app.sms8.io/ajax/otp-send.php
- phone — obligatorio, formato E.164
- length — 4 a 8 dígitos, por defecto 6
- expires_in — 60 a 900 segundos, por defecto 300
- max_attempts — 1 a 10, por defecto 5
- template — texto con el placeholder
{code} - option / devices / useRandomDevice — selector de dispositivo
Endpoint de verificación
POST https://app.sms8.io/ajax/otp-verify.php
- phone — obligatorio, formato E.164
- code — el código que tecleó el usuario
Respuestas:
{verified: true}en éxito{verified: false, reason: "code_mismatch", attempts_left: 4}- Otros motivos:
expired,not_found,max_attempts
Llamadas listas para usar
Enviar un OTP
curl -X POST https://app.sms8.io/ajax/otp-send.php \ -H "Authorization: Bearer YOUR_SMS8_API_KEY" \ -d "phone=+34612345678" # Cambia los valores por defecto: # -d "length=6" -d "expires_in=300" # -d "max_attempts=5" # -d "template=Tu codigo es {code}, caduca pronto." # Elige dispositivo o SIM emisor: # -d "option=0" --data-urlencode 'devices=["DEVICE_ID"]' # -d "option=1" # reparte entre todos los dispositivos # -d "option=2" # reparte entre todas las SIMs # -d "useRandomDevice=1" # un emisor al azar
Verificar el código
curl -X POST https://app.sms8.io/ajax/otp-verify.php \ -H "Authorization: Bearer YOUR_SMS8_API_KEY" \ -d "phone=+34612345678" \ -d "code=123456" # Exito: {"verified": true} # Fallo: {"verified": false, "reason": "code_mismatch", "attempts_left": 4}
Desde un asistente de IA (MCP)
Si Claude Code, Cursor o Windsurf están conectados a mcp.sms8.io, pídeles: "Mete verificación por SMS en el signup usando sms8 MCP". El asistente llama a send_otp y verify_otp con tus valores por defecto y envuelve las rutas de registro o login que ya tienes.
Configura una vez desde el panel
Defines los valores de respaldo una sola vez. Se aplican cuando el cliente deja el campo vacío. Los topes duros se respetan siempre.
Longitud del código
4 a 8 dígitos. Por defecto 6. Más corto, más memorable; más largo, más resistente.
Caducidad
60 a 900 segundos. Por defecto 300 (5 min). Corta para limitar el reuso, suficiente para que el usuario teclee.
Intentos de verificación
1 a 10 intentos antes de bloquear el código. Por defecto 5.
Cooldown de reenvío
30 a 600 segundos entre envíos al mismo número. Por defecto 60.
Plantilla del SMS
Adapta el texto al tono de tu marca. Solo tiene que contener el placeholder {code}.
Edita tus valores
La vista previa refleja cada cambio en tiempo real. Manda un OTP real a tu móvil y prueba el viaje completo.
Topes duros que protegen a tus clientes
5 OTPs por número cada 24h
El tope más duro y no se puede subir desde la cuenta. Aunque se filtre tu clave, ningún número aguanta más de 5 códigos en 24h móviles.
Comprobaciones en transacción
El cooldown y el tope diario corren bajo SELECT ... FOR UPDATE. Dos peticiones simultáneas no se cuelan por la puerta de atrás.
Verificación en tiempo constante
verify_otp compara con hash_equals. Sin fugas por timing.
Solo POST, sin cookies
Los GET devuelven 405. Las cookies se ignoran en el auth. El CSRF por etiqueta de imagen no existe.
Tope de intentos por OTP
Por defecto 5 intentos fallidos por código. Después, el código se bloquea y hace falta un nuevo send_otp.
Errores genéricos
Las excepciones internas devuelven Internal error. Los stack traces nunca llegan al cliente.
Preguntas sobre OTP
¿Cómo envío un OTP con SMS8?
Manda un POST a https://app.sms8.io/ajax/otp-send.php con el número. El endpoint acepta la cabecera Authorization: Bearer. Campos opcionales: length (4 a 8), expires_in (60 a 900s), max_attempts (1 a 10), template, y selector de dispositivo.
¿Cómo funciona verify_otp?
Envía el número y el código que tecleó el usuario a https://app.sms8.io/ajax/otp-verify.php. El servidor compara en tiempo constante con el último OTP y devuelve verified: true o verified: false. Si falla, te da reason y attempts_left.
¿Cuál es el tope antiabuso de OTPs?
Cualquier número recibe como mucho 5 OTPs en una ventana de 24 horas. Es un tope duro no configurable, que protege al destinatario aunque se filtre tu clave.
¿Necesito A2P 10DLC para los OTPs por SMS8?
No. SMS8 manda los OTPs por tu Android emparejado y tu SIM, así que no hace falta registro A2P 10DLC.
¿Puede el asistente añadir la verificación automáticamente?
Sí. El Skill que viene con Claude Code le enseña al asistente cuándo llamar a send_otp y verify_otp. Con un prompt como añade verificación a /signup ya tira.