Справочник API WapFlow OTP
Отправляйте и проверяйте коды подтверждения с собственного номера WhatsApp. Все ответы возвращаются в формате JSON.
Базовый адрес: https://wapflow.net/api/otp/v1
Аутентификация
Передавайте заголовок Authorization: Bearer <key> в каждом запросе. Ключи создаются на странице WapFlow OTP в панели WapFlow; боевые ключи начинаются с wfo_live_, тестовые — с wfo_test_. Ключ показывается только один раз, при создании: сохраните его в надёжном месте и используйте только на сервере.
Успешный ответ выглядит так: { "success": true, ... }; ответ с ошибкой — так: { "success": false, "error": { "code": "...", "message": "..." } }.
Отправка кода
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"
}
{
"success": true,
"request_id": "req_...",
"phone": "905321234567",
"expires_at": "2026-11-12T10:05:00.000Z",
"status": "sent" // "sent" | "queued"
}
Проверка кода
phone и code обязательны. Если передан request_id, проверяется именно этот запрос; если нет, проверяется последний не истёкший код, отправленный на этот номер с этим ключом. После 5 неверных попыток запрос блокируется, а подтверждённый код повторно использовать нельзя.
{ "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 }
Проверка статуса
Возвращает статус запроса: queued, sent, delivered, read, failed, verified или expired.
{ "success": true, "request_id": "req_...", "status": "delivered",
"sent_at": "...", "delivered_at": "...", "verified_at": null }
Проверка соединения
Показывает, что ключ действителен, ваш тариф, количество подключённых аккаунтов и использование квоты за этот месяц (кнопка «Проверить соединение» в плагине 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 | Код | Значение |
|---|---|---|
| 400 | invalid_request | Тело запроса или параметры некорректны. |
| 401 | invalid_key | Ключ API недействителен или отозван. |
| 402 | no_subscription | У этого аккаунта нет подписки WapFlow OTP. |
| 402 | subscription_expired | Срок подписки истёк; продлите её. |
| 403 | sales_disabled | Сервис временно недоступен. |
| 422 | invalid_phone | Номер телефона некорректен. |
| 429 | rate_limited | Превышено ограничение частоты; повторите запрос через retry_after секунд, указанных в ответе. |
| 429 | quota_exceeded | Квота кодов на этот месяц исчерпана. |
| 429 | daily_limit_reached | Достигнут дневной лимит отправки подключённых аккаунтов WhatsApp; повторите попытку через количество секунд, указанное в retry_after в ответе (на следующий день в 00:00 по стамбульскому времени). Квота не расходуется. |
| 503 | no_account_connected | Нет подключённого и включённого аккаунта WhatsApp. |
| 503 | send_failed | Не удалось отправить сообщение; повторите попытку немного позже. |
Ограничения частоты
- На один номер: 1 код за 60 секунд, 5 в час и 10 в день.
- На ключ API: 60 отправок в минуту.
- На IP-адрес: 120 запросов в минуту (включая проверку).
- Проверка: 10 попыток в минуту на номер и не более 5 неверных попыток на один код.
- Месячная квота зависит от тарифа; когда она исчерпана, возвращается
quota_exceeded. Тестовые ключи квоту не расходуют.
Прогрев аккаунта и дневной лимит
- Новые подключённые номера WhatsApp проходят прогрев, чтобы снизить риск блокировки: первые 3 дня — 30 кодов в день, дни 4–7 — 100 кодов в день, затем 500 кодов в день на аккаунт (значения по умолчанию).
- Аккаунт, достигший дневного лимита, пропускается, и коды отправляются с других подключённых аккаунтов. Если все аккаунты исчерпали лимит, возвращается
429 daily_limit_reached; счётчик обнуляется в полночь по стамбульскому времени. - Для большего объёма выберите пакет с несколькими аккаунтами. Тестовые ключи не подпадают под эти ограничения.
Тестовые ключи
Ключи, начинающиеся с wfo_test_, не отправляют сообщения в WhatsApp и не расходуют квоту; код возвращается в поле test_code. Правила отправки и ограничения частоты такие же, как у боевых ключей, и активная подписка по-прежнему нужна. Чтобы перейти на боевой режим, просто замените ключ.
{ "success": true, "request_id": "req_...", "status": "sent", "test_code": "482913" }
Формат номера телефона
- Номер приводится к цифрам (символы +, пробелы и дефисы удаляются) и должен содержать от 10 до 15 цифр.
- Указывайте код страны (например,
905321234567). 11-значный номер, начинающийся с 0, считается турецким, и к нему добавляется 90. - Некорректный номер возвращает
422 invalid_phone.
Замечания по безопасности
- Коды генерируются криптографически стойким генератором случайных чисел и никогда не хранятся в открытом виде.
- Никогда не используйте ключ API в браузере, мобильном приложении или публичном коде; вызывайте API с вашего сервера.
- Всегда проверяйте код на сервере с помощью
/verify. - WapFlow OTP — не официальный API WhatsApp и не гарантирует доставку; для критичных операций держите резервный канал.
Плагин WordPress
- Скачайте wapflow-otp.zip.
- В панели администратора WordPress откройте Плагины → Добавить новый → Загрузить плагин, загрузите zip-архив и активируйте его.
- В настройках плагина вставьте ключ API, созданный в панели WapFlow.
- Кнопкой «Проверить соединение» проверьте ключ и свой тариф.
- Сначала попробуйте с тестовым ключом, затем введите боевой ключ.