Referencia de la API de WapFlow OTP
Envíe y verifique códigos de verificación desde su propio número de WhatsApp. Todas las respuestas son JSON.
URL base: https://wapflow.net/api/otp/v1
Autenticación
Envíe la cabecera Authorization: Bearer <key> en cada solicitud. Las claves se crean en la página WapFlow OTP de su panel de WapFlow; las claves de producción empiezan por wfo_live_ y las de prueba por wfo_test_. La clave solo se muestra una vez, al crearla: guárdela de forma segura y utilícela únicamente en su servidor.
Una respuesta correcta tiene este aspecto: { "success": true, ... }; un error, este: { "success": false, "error": { "code": "...", "message": "..." } }.
Enviar un código
phone (obligatorio) es el número del destinatario. Opcionales: code_length (4–8), ttl (60–900 s), lang (p. ej. tr, en) y app_name. Lo que omita se toma de la configuración de su panel.
{
"phone": "905321234567",
"code_length": 6,
"ttl": 300,
"lang": "tr",
"app_name": "Acme"
}
{
"success": true,
"request_id": "req_...",
"phone": "905321234567",
"expires_at": "2026-11-12T10:05:00.000Z",
"status": "sent" // "sent" | "queued"
}
Verificar un código
phone y code son obligatorios. Con request_id se comprueba esa solicitud exacta; sin él, el último código no caducado enviado a ese número con esta clave. Tras 5 intentos incorrectos la solicitud se bloquea, y un código ya verificado no puede reutilizarse.
{ "request_id": "req_...", "phone": "905321234567", "code": "123456" }
{ "success": true, "valid": true }
{ "success": true, "valid": false,
"reason": "invalid_code", // invalid_code | expired | too_many_attempts | already_verified | not_found
"attempts_left": 3 }
Consultar estado
Devuelve el estado de la solicitud: queued, sent, delivered, read, failed, verified o expired.
{ "success": true, "request_id": "req_...", "status": "delivered",
"sent_at": "...", "delivered_at": "...", "verified_at": null }
Probar la conexión
Muestra que la clave es válida, su plan, el número de cuentas conectadas y el uso de la cuota de este mes (lo utiliza el botón “Probar conexión” del plugin de WordPress).
{ "success": true, "plan": "otp-2",
"accounts": { "limit": 2, "connected": 1 },
"quota": { "monthly": 15000, "used": 42, "period": "2026-11" },
"ends_at": "2026-12-12T10:00:00.000Z", "mode": "live" }
Ejemplos
Estos ejemplos envían un código y luego verifican lo que introduce el usuario. Sustituya wfo_live_XXXX por su propia clave.
# 1) send
curl -X POST https://wapflow.net/api/otp/v1/send \
-H "Authorization: Bearer wfo_live_XXXX" \
-H "Content-Type: application/json" \
-d '{"phone":"905321234567","app_name":"Acme"}'
# 2) verify
curl -X POST https://wapflow.net/api/otp/v1/verify \
-H "Authorization: Bearer wfo_live_XXXX" \
-H "Content-Type: application/json" \
-d '{"request_id":"req_...","phone":"905321234567","code":"123456"}'<?php
function wapflow_otp(string $path, array $body): array {
$ch = curl_init('https://wapflow.net/api/otp/v1' . $path);
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 15,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('WAPFLOW_OTP_KEY'),
'Content-Type: application/json',
],
CURLOPT_POSTFIELDS => json_encode($body),
]);
$res = json_decode(curl_exec($ch), true) ?: [];
curl_close($ch);
return $res;
}
$sent = wapflow_otp('/send', ['phone' => '905321234567', 'app_name' => 'Acme']);
// ... kullanıcı kodu girince:
$check = wapflow_otp('/verify', ['request_id' => $sent['request_id'], 'phone' => '905321234567', 'code' => $_POST['code']]);
if (!empty($check['valid'])) { /* giriş başarılı */ }const BASE = 'https://wapflow.net/api/otp/v1';
async function otp(path, body) {
const res = await fetch(BASE + path, {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.WAPFLOW_OTP_KEY}`,
'Content-Type': 'application/json',
},
body: JSON.stringify(body),
});
return res.json();
}
const sent = await otp('/send', { phone: '905321234567', app_name: 'Acme' });
// ... when the user submits the code:
const check = await otp('/verify', { request_id: sent.request_id, phone: '905321234567', code: '123456' });
if (check.valid) { /* signed in */ }import os
import requests
BASE = "https://wapflow.net/api/otp/v1"
HEADERS = {"Authorization": "Bearer " + os.environ["WAPFLOW_OTP_KEY"]}
def otp(path, body):
return requests.post(BASE + path, json=body, headers=HEADERS, timeout=15).json()
sent = otp("/send", {"phone": "905321234567", "app_name": "Acme"})
# ... when the user submits the code:
check = otp("/verify", {"request_id": sent["request_id"], "phone": "905321234567", "code": "123456"})
if check.get("valid"):
pass # signed inCódigos de error
| HTTP | Código | Significado |
|---|---|---|
| 400 | invalid_request | El cuerpo de la solicitud o los parámetros no son válidos. |
| 401 | invalid_key | La clave de API no es válida o ha sido revocada. |
| 402 | no_subscription | Esta cuenta no tiene una suscripción a WapFlow OTP. |
| 402 | subscription_expired | La suscripción ha caducado; renuévela. |
| 403 | sales_disabled | El servicio no está disponible temporalmente. |
| 422 | invalid_phone | El número de teléfono no es válido. |
| 429 | rate_limited | Se ha superado el límite de uso; reintente después de los segundos indicados en retry_after de la respuesta. |
| 429 | quota_exceeded | Se ha agotado la cuota de códigos de este mes. |
| 429 | daily_limit_reached | Se ha alcanzado el límite diario de envío de las cuentas de WhatsApp conectadas; vuelva a intentarlo después de los segundos indicados en retry_after de la respuesta (al día siguiente a las 00:00, hora de Estambul). No se consume cuota. |
| 503 | no_account_connected | No hay ninguna cuenta de WhatsApp conectada y activa. |
| 503 | send_failed | No se pudo enviar el mensaje; inténtelo de nuevo en breve. |
Límites de uso
- Por número: 1 código cada 60 segundos, 5 por hora y 10 al día.
- Por clave de API: 60 envíos por minuto.
- Por dirección IP: 120 solicitudes por minuto (incluida la verificación).
- Verificación: 10 intentos por minuto y número, y como máximo 5 intentos incorrectos por código.
- La cuota mensual depende de su plan; cuando se agota, se devuelve
quota_exceeded. Las claves de prueba no consumen cuota.
Calentamiento de la cuenta y límite diario
- Los números de WhatsApp recién conectados se calientan gradualmente para reducir el riesgo de bloqueo: 30 códigos al día durante los primeros 3 días, 100 al día los días 4–7 y luego 500 al día por cuenta (valores predeterminados).
- Una cuenta que alcanza su límite diario se omite y los códigos salen desde sus otras cuentas conectadas. Si todas están llenas, se devuelve
429 daily_limit_reached; el contador se reinicia a medianoche, hora de Estambul. - Para más volumen, elija un paquete con varias cuentas. Las claves de prueba no se ven afectadas por estos límites.
Claves de prueba
Las claves que empiezan por wfo_test_ no envían ningún mensaje de WhatsApp ni consumen cuota; el código se devuelve en el campo test_code. Las reglas de envío y de límites son las mismas que con las claves de producción, y sigue siendo necesaria una suscripción activa. Para pasar a producción, basta con cambiar la clave.
{ "success": true, "request_id": "req_...", "status": "sent", "test_code": "482913" }
Formato del número de teléfono
- El número se reduce a dígitos (se eliminan +, espacios y guiones) y debe tener entre 10 y 15 dígitos.
- Incluya el prefijo del país (p. ej.
905321234567). Un número de 11 dígitos que empiece por 0 se trata como turco y se le antepone 90. - Un número no válido devuelve
422 invalid_phone.
Notas de seguridad
- Los códigos se generan con un generador aleatorio criptográficamente seguro y nunca se guardan en texto plano.
- No utilice la clave de API en un navegador, en una aplicación móvil ni en código público; realice las llamadas desde su servidor.
- Compruebe siempre el código en el servidor con
/verify. - WapFlow OTP no es la API oficial de WhatsApp y no garantiza la entrega; mantenga un canal de respaldo para las acciones críticas.
Plugin de WordPress
- Descargue wapflow-otp.zip.
- En el administrador de WordPress vaya a Plugins → Añadir nuevo → Subir plugin, suba el archivo zip y actívelo.
- En la configuración del plugin, pegue la clave de API que creó en el panel de WapFlow.
- Use el botón “Probar conexión” para comprobar la clave y su plan.
- Pruébelo primero con una clave de prueba y después cambie a la clave de producción.