WapFlow OTP API 参考

用您自己的 WhatsApp 号码发送并验证验证码。所有响应均为 JSON。

基础地址: https://wapflow.net/api/otp/v1

身份验证

每个请求都需发送 Authorization: Bearer <key> 请求头。您可在 WapFlow 面板的 WapFlow OTP 页面创建密钥;正式密钥以 wfo_live_ 开头,测试密钥以 wfo_test_ 开头。密钥仅在创建时显示一次——请妥善保存,并且只在服务器端使用。

成功响应形如 { "success": true, ... };错误响应形如 { "success": false, "error": { "code": "...", "message": "..." } }。

发送验证码

POST/send

phone(必填)为接收者号码。可选项:code_length(4–8)、ttl(60–900 秒)、lang(如 tr、en)和 app_name。未提供的参数将使用您的面板设置。

请求
{
  "phone": "905321234567",
  "code_length": 6,
  "ttl": 300,
  "lang": "tr",
  "app_name": "Acme"
}
响应 (200)
{
  "success": true,
  "request_id": "req_...",
  "phone": "905321234567",
  "expires_at": "2026-11-12T10:05:00.000Z",
  "status": "sent"            // "sent" | "queued"
}

验证验证码

POST/verify

phone 和 code 为必填项。提供 request_id 时,将校验该特定请求;不提供时,则校验使用此密钥发送到该号码的最新未过期验证码。连续 5 次错误尝试后,该请求将被锁定;已验证的验证码不可重复使用。

请求
{ "request_id": "req_...", "phone": "905321234567", "code": "123456" }
响应 (200)
{ "success": true, "valid": true }

{ "success": true, "valid": false,
  "reason": "invalid_code",     // invalid_code | expired | too_many_attempts | already_verified | not_found
  "attempts_left": 3 }

查询状态

GET/status/:request_id

返回请求状态:queued、sent、delivered、read、failed、verified 或 expired。

{ "success": true, "request_id": "req_...", "status": "delivered",
  "sent_at": "...", "delivered_at": "...", "verified_at": null }

测试连接

GET/me

显示密钥是否有效、您的套餐、已连接账户数量以及本月配额使用情况(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" }

示例

以下示例发送验证码,然后验证用户输入的验证码。请将 wfo_live_XXXX 替换为您自己的密钥。

# 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 in

错误代码

HTTP代码含义
400invalid_request请求正文或参数无效。
401invalid_keyAPI 密钥无效或已被撤销。
402no_subscription该账户没有 WapFlow OTP 订阅。
402subscription_expired订阅已过期;请续订。
403sales_disabled服务暂时不可用。
422invalid_phone电话号码无效。
429rate_limited超出速率限制;请在响应中 retry_after 秒后重试。
429quota_exceeded本月验证码配额已用完。
429daily_limit_reached已连接的 WhatsApp 账号的每日发送上限已达到;请在 retry_after 秒后(次日 00:00,伊斯坦布尔时间)重试。不会消耗配额。
503no_account_connected没有已连接且已启用的 WhatsApp 账户。
503send_failed消息发送失败;请稍后重试。

速率限制

账号预热与每日上限

测试密钥

以 wfo_test_ 开头的密钥不发送 WhatsApp 消息,也不消耗配额;验证码通过 test_code 字段返回。发送和速率限制规则与正式密钥相同,且仍需有效订阅。正式上线时,只需替换密钥。

{ "success": true, "request_id": "req_...", "status": "sent", "test_code": "482913" }

电话号码格式

安全说明

WordPress 插件

  1. 下载 wapflow-otp.zip。
  2. 在 WordPress 后台进入 插件 → 安装插件 → 上传插件,上传 zip 文件并启用。
  3. 在插件设置中,粘贴您在 WapFlow 面板中创建的 API 密钥。
  4. 使用“测试连接”按钮检查密钥和您的套餐。
  5. 先用测试密钥试用,然后再切换为正式密钥。