OTP API
Документация (RU) ▼
Базовый URL: https://sms-acktiwator.ru/api/otp/
Метод: GET или POST (параметры можно передавать query string или form-urlencoded).
Параметры: основной параметр — action (название метода).
Авторизация: для защищённых методов требуется параметр key (ваш API‑ключ из раздела API).
Лимиты: защищённые методы — 50 запросов/минуту на ключ; getPrices — 10 запросов/минуту (без ключа — по IP, с ключом — по ключу).
1) getPrices
Назначение: актуальные цены и количество доступных номеров по странам и сервисам.
Параметры:
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
action | строка | да | getPrices |
Запрос:
https://sms-acktiwator.ru/api/otp/?action=getPrices
Ответ: JSON вида { "Country_ID": { "Service_Code": { "cost": "0.50", "count": 100 } } }
{
"1": {
"wa": { "cost": "0.50", "count": 100 },
"tg": { "cost": "0.71", "count": 250 }
}
}
2) getCountries
Назначение: список поддерживаемых стран (ID и названия).
Параметры:
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
action | строка | да | getCountries |
Запрос:
https://sms-acktiwator.ru/api/otp/?action=getCountries
Ответ: JSON (ключ — ID страны):
{
"43": { "id": 43, "rus": "Германия", "eng": "Germany", "chn": "德国", "visible": 1 }
}
3) getServicesList
Назначение: список сервисов (код + отображаемое название).
Параметры:
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
action | строка | да | getServicesList |
Запрос:
https://sms-acktiwator.ru/api/otp/?action=getServicesList
Ответ: JSON:
{
"status": "success",
"services": [
{ "id": "1", "code": "wa", "name": "WhatsApp" },
{ "id": "2", "code": "tg", "name": "Telegram" }
]
}
4) getBalance (требует key)
Назначение: вернуть баланс пользователя в системе.
Параметры:
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
action | строка | да | getBalance |
key | строка | да | Ваш API‑ключ |
Запрос:
https://sms-acktiwator.ru/api/otp/?action=getBalance&key=YOUR_API_KEY
Ответ (text/plain):
ACCESS_BALANCE:12.50
Ошибки:
BAD_KEY— ключ не указан, неверный или отключён.CHANNEL_LIMIT— превышен лимит запросов (50/мин на ключ).
5) getNumber (требует key)
Назначение: заказать номер для приёма SMS.
Параметры:
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
action | строка | да | getNumber |
key | строка | да | Ваш API‑ключ |
country | строка (число) | да | ID страны (пример: 43) |
service | строка | да | Код сервиса (пример: wa) |
maxPrice | число (4 знака) | нет | Максимальная цена, за которую вы готовы купить номер (пример: 0.5000) |
key— API‑ключ (обяз.)country— ID страны (обяз., числовая строка)service— код сервиса (обяз., напримерwa,tg,vk,fb)maxPrice— необязательный потолок цены (Decimal, до 4 знаков после точки). Если продажная цена номера (та же, что вgetPrices) вышеmaxPrice— номер не покупается и возвращаетсяNO_NUMBERS. Без параметра — покупка по текущей цене.
Запрос:
https://sms-acktiwator.ru/api/otp/?action=getNumber&key=YOUR_API_KEY&country=43&service=wa&maxPrice=0.5000
Ответ (text/plain):
ACCESS_NUMBER:12345:380991234567
Ошибки:
BAD_KEY— ключ не указан, неверный или отключён.BAD_COUNTRY— страна не указана или country не найден.BAD_SERVICE— сервис не указан или не поддерживается.BAD_MAX_PRICE—maxPriceпередан, но не является корректным неотрицательным числом.NO_BALANCE— недостаточно средств на балансе пользователя.NO_NUMBERS— нет доступных номеров по указанным параметрам (в т.ч. когда цена вышеmaxPrice).CHANNEL_LIMIT— превышен лимит запросов (50/мин на ключ).UNKNOWN_ERROR— внутренняя ошибка сервера.
6) getStatus (требует key)
Назначение: проверить, получено ли SMS и код.
Параметры:
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
action | строка | да | getStatus |
key | строка | да | Ваш API‑ключ |
activationId | строка (число) | да | ID активации из getNumber |
Запрос:
https://sms-acktiwator.ru/api/otp/?action=getStatus&key=YOUR_API_KEY&activationId=12345
Ответы (text/plain):
STATUS_WAIT_CODE— код ещё не полученSTATUS_OK:123456— код полученNO_ACTIVATION— активация не найдена, отменена или истекла (тело завершается переводом строки\n)BAD_KEY— неверный ключ
Расшифровка:
STATUS_WAIT_CODE— ожидайте: повторите запрос через несколько секунд.STATUS_OK:CODE— код получен, можно завершать активацию черезsetStatusсоstatus=6.NO_ACTIVATION— терминальный ответ: активация не найдена / отменена / истекла, прекратите поллинг. Тело завершается переводом строки\n— учитывайте это при точном сравнении/построчном чтении.BAD_KEY— ключ не указан, неверный или отключён.
Как поллить: опрашивайте getStatus в цикле до терминального ответа — STATUS_OK:CODE (код получен) или NO_ACTIVATION (активация закрыта). STATUS_WAIT_CODE — промежуточный, повторяйте запрос.
7) setStatus (требует key)
Назначение: изменить статус активации.
Параметры:
| Параметр | Тип | Обязателен | Описание |
|---|---|---|---|
action | строка | да | setStatus |
key | строка | да | Ваш API‑ключ |
activationId | строка (число) | да | ID активации |
status | строка (число) | да | Новый статус: 3, 6 или 8 |
Значения status:
3— запросить ещё одно SMS6— завершить активацию8— отменить активацию
⚠️ Важно про средства:
6— завершить активацию: средства списываются окончательно (возврата нет). Отправляйте только послеSTATUS_OK:CODE— то есть когда код уже получен.8— отменить активацию: средства возвращаются на баланс. Отправляйте, если код так и не пришёл.- Если код не получен, всегда отправляйте
status=8, а не6— иначе активация будет оплачена без возврата средств.
Запрос:
https://sms-acktiwator.ru/api/otp/?action=setStatus&key=YOUR_API_KEY&activationId=12345&status=6
Ответы (text/plain):
ACCESS_ACTIVATION— активация завершена.ACCESS_CANCEL— активация отменена.STATUS_WAIT_CODE— запрос на повторную SMS принят.NO_ACTIVATION— активация не найдена.BAD_KEY— ключ не указан, неверный или отключён.BAD_STATUS— неверное значениеstatus, некорректные параметры, либоstatus=6при не полученном коде (завершать можно только послеSTATUS_OK:CODE).
Webhooks (пуш-уведомления)
Вместо поллинга вы можете получать события на свой HTTPS-эндпоинт. Мы отправляем POST при двух событиях:
sms.received— на арендованный номер пришла входящая SMS (Numbers API).otp.code— по вашей OTP-активации пришёл код (OTP API).
Оба события идут на один и тот же URL; тип — в поле event тела и в заголовке X-Turbon-Event.
Настройка webhook
Эндпоинт: https://sms-acktiwator.ru/api/webhook (аутентификация параметром key). Также настраивается в форме Webhook выше на этой странице (для авторизованных).
| action | Метод | Описание |
|---|---|---|
set | POST | Задать/изменить url (только https:// и доменное имя; literal-IP и localhost запрещены). Включает webhook. |
get | GET | Текущая конфигурация (без секрета). |
disable | POST | Выключить webhook. |
rotate_secret | POST | Сгенерировать новый секрет подписи (возвращается один раз). |
test | POST | Отправить тестовое событие webhook.test на ваш URL. |
deliveries | GET | Последние 50 доставок со статусами (для отладки). |
Пример — задать URL:
POST https://sms-acktiwator.ru/api/webhook
Content-Type: application/x-www-form-urlencoded
key=YOUR_API_KEY&action=set&url=https://your-host.com/webhook
Ответ (200):
{
"webhook": {
"url": "https://your-host.com/webhook",
"is_active": true,
"is_enabled": true,
"has_secret": true,
"auto_disabled_at": null,
"consecutive_failures": 0
}
}
Секрет подписи возвращается один раз — при rotate_secret:
{ "secret": "e3b0c44298fc1c149afbf4c8996fb924..." }
Ошибки: неверный ключ — 403 BAD_KEY; webhooks выключены — 403 DISABLED; недопустимый URL — 400 BAD_URL; слишком много запросов — 429 CHANNEL_LIMIT (мутации: 20/мин).
Структура пуш-запроса
Мы отправляем на ваш URL POST с Content-Type: application/json и заголовками:
| Заголовок | Описание |
|---|---|
X-Turbon-Event | Тип события: sms.received или otp.code |
X-Turbon-Delivery | Идентификатор события id (для дедупликации) |
X-Turbon-Signature | Подпись: t=<unix>,v1=<HMAC-SHA256> |
User-Agent | turbon-rent-webhooks/1.0 |
Общий конверт тела:
{
"event": "sms.received",
"id": "3f9a1c2b4d5e6f708192a3b4c5d6e7f8",
"created_at": "2026-07-11T10:15:30Z",
"api_version": "2026-07-11",
"data": { ... }
}
data для sms.received:
{
"rental_id": 1000000123,
"phone": "+48123456789",
"from": "Google",
"text": "G-123456 is your code",
"received_at": "2026-07-11T10:15:29Z"
}
| Поле | Тип | Описание |
|---|---|---|
rental_id | int|null | ID аренды (как в Numbers API). null для offline-аренды. |
phone | string | Ваш номер-получатель |
from | string | Отправитель SMS |
text | string | Текст сообщения |
received_at | string | ISO-8601 UTC, время получения |
data для otp.code:
{
"activation_id": 456,
"phone": "+79991234567",
"service": "telegram",
"country": "ru",
"code": "123456",
"received_at": "2026-07-11T10:15:29Z"
}
| Поле | Тип | Описание |
|---|---|---|
activation_id | int | ID активации (тот же, что вернул getNumber в OTP API: ACCESS_NUMBER:<activation_id>:<phone>) |
phone | string | Номер активации |
service | string | Код сервиса |
country | string | ISO страны |
code | string | Полученный код |
received_at | string | ISO-8601 UTC |
Проверка подписи
Заголовок X-Turbon-Signature имеет вид t=<unix>,v1=<hex>. Проверка:
- Возьмите сырое тело запроса (байты, как получили) и значение
t. - Вычислите
HMAC-SHA256(secret, "<t>.<raw_body>")в hex и сравните сv1(constant-time). - Отклоняйте запрос, если
|now − t| > 5 минут(защита от replay).
Пример (Python):
import hmac, hashlib, time
def verify(secret, header, raw_body):
parts = dict(p.split('=', 1) for p in header.split(','))
t, v1 = parts['t'], parts['v1']
if abs(time.time() - int(t)) > 300:
return False
expected = hmac.new(secret.encode(), f"{t}.{raw_body}".encode(),
hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, v1)
Доставка, ретраи и идемпотентность
- Отвечайте
2xxв течение 10 секунд, чтобы подтвердить приём. - Не-2xx или таймаут → повтор с возрастающей задержкой: ≈1м, 5м, 15м, 1ч, 3ч, 6ч, 12ч (до 8 попыток, ~22 часа), затем событие отбрасывается.
- Доставка at-least-once: одно событие может прийти повторно (например, если ваш
2xxне дошёл). Дедуплицируйте по полюid(оно же в заголовкеX-Turbon-Delivery). - После 20 подряд полностью неудачных событий webhook авто-выключается; включите заново через
set. - Служебные/технические SMS не пушатся.
Documentation (EN) ▼
Base URL: https://sms-acktiwator.ru/api/otp/
Method: GET or POST (parameters can be sent via query string or form-urlencoded body).
Parameters: main parameter is action (method name).
Auth: protected methods require key (your API key from the API page).
Limits: protected methods — 50 requests/minute per key; getPrices — 10 requests/minute (without key — per IP, with key — per key).
1) getPrices
Purpose: current prices and available number counts by countries and services.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | yes | getPrices |
Request:
https://sms-acktiwator.ru/api/otp/?action=getPrices
Response: JSON: { "Country_ID": { "Service_Code": { "cost": "0.50", "count": 100 } } }
{
"1": {
"wa": { "cost": "0.50", "count": 100 },
"tg": { "cost": "0.71", "count": 250 }
}
}
2) getCountries
Purpose: list of supported countries.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | yes | getCountries |
Request:
https://sms-acktiwator.ru/api/otp/?action=getCountries
Response: JSON object keyed by Country ID:
{
"43": { "id": 43, "rus": "Германия", "eng": "Germany", "chn": "德国", "visible": 1 }
}
3) getServicesList
Purpose: list of supported services.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | yes | getServicesList |
Request:
https://sms-acktiwator.ru/api/otp/?action=getServicesList
Response:
{
"status": "success",
"services": [
{ "id": "1", "code": "wa", "name": "WhatsApp" },
{ "id": "2", "code": "tg", "name": "Telegram" }
]
}
4) getBalance (requires key)
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | yes | getBalance |
key | string | yes | Your API key |
https://sms-acktiwator.ru/api/otp/?action=getBalance&key=YOUR_API_KEY
Response (text/plain): ACCESS_BALANCE:12.50
Errors:
BAD_KEY— missing/invalid/disabled key.CHANNEL_LIMIT— rate limit exceeded (50/min per key).
5) getNumber (requires key)
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | yes | getNumber |
key | string | yes | Your API key |
country | string (number) | yes | Country ID (e.g. 43) |
service | string | yes | Service code (e.g. wa) |
maxPrice | number (4 decimals) | no | The maximum price for which you are ready to buy a number (e.g. 0.5000) |
maxPrice — optional price cap (Decimal, up to 4 decimal places). If the number's sale price (same as in getPrices) exceeds maxPrice, the number is not purchased and NO_NUMBERS is returned. Omit for purchase at the current price.
https://sms-acktiwator.ru/api/otp/?action=getNumber&key=YOUR_API_KEY&country=43&service=wa&maxPrice=0.5000
Response (text/plain): ACCESS_NUMBER:12345:380991234567
Errors:
BAD_KEY— missing/invalid/disabled key.BAD_COUNTRY— missing/invalid country value.BAD_SERVICE— missing/invalid service value.BAD_MAX_PRICE—maxPricewas provided but is not a valid non-negative number.NO_BALANCE— insufficient user balance.NO_NUMBERS— no available numbers for the given parameters (including when the price exceedsmaxPrice).CHANNEL_LIMIT— rate limit exceeded (50/min per key).UNKNOWN_ERROR— internal server error.
6) getStatus (requires key)
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | yes | getStatus |
key | string | yes | Your API key |
activationId | string (number) | yes | Activation ID from getNumber |
https://sms-acktiwator.ru/api/otp/?action=getStatus&key=YOUR_API_KEY&activationId=12345
Responses (text/plain):
STATUS_WAIT_CODE— SMS code not received yet.STATUS_OK:123456— code received.NO_ACTIVATION— activation not found, cancelled or expired. The response body ends with a newline\n(NO_ACTIVATION\n).BAD_KEY— missing/invalid/disabled key.
Notes: Poll getStatus in a loop until a terminal response — STATUS_OK:CODE (code received) or NO_ACTIVATION (activation closed). After STATUS_OK:CODE you may finish the activation via setStatus with status=6.
7) setStatus (requires key)
https://sms-acktiwator.ru/api/otp/?action=setStatus&key=YOUR_API_KEY&activationId=12345&status=6
Status values: 3 resend, 6 complete, 8 cancel.
⚠️ Important about funds:
6— complete activation: funds are charged permanently (no refund). Send only afterSTATUS_OK:CODE, i.e. once the code has been received.8— cancel activation: funds are refunded to your balance. Send if the code never arrived.- If the code was not received, always send
status=8, not6— otherwise the activation is paid for with no refund.
Parameters:
| Parameter | Type | Required | Description |
|---|---|---|---|
action | string | yes | setStatus |
key | string | yes | Your API key |
activationId | string (number) | yes | Activation ID |
status | string (number) | yes | New status: 3, 6 or 8 |
Responses (text/plain):
ACCESS_ACTIVATION— activation completed.ACCESS_CANCEL— activation canceled.STATUS_WAIT_CODE— resend requested.NO_ACTIVATION— activation not found.BAD_KEY— missing/invalid/disabled key.BAD_STATUS— invalid status value, bad parameters, orstatus=6while no code was received (complete only afterSTATUS_OK:CODE).
Webhooks (push notifications)
Instead of polling, you can receive events on your HTTPS endpoint. We send a POST for two events:
sms.received— an inbound SMS arrived on your rented number (Numbers API).otp.code— a code arrived for your OTP activation (OTP API).
Both events go to the same URL; the type is in the body field event and the X-Turbon-Event header.
Configuring the webhook
Endpoint: https://sms-acktiwator.ru/api/webhook (authenticate with the key parameter). You can also configure it in the Webhook form above on this page (when signed in).
| action | Method | Description |
|---|---|---|
set | POST | Set/update url (https:// and a domain name only; literal IPs and localhost are rejected). Enables the webhook. |
get | GET | Current configuration (without the secret). |
disable | POST | Disable the webhook. |
rotate_secret | POST | Generate a new signing secret (returned once). |
test | POST | Send a webhook.test event to your URL. |
deliveries | GET | Last 50 deliveries with statuses (for debugging). |
Example — set the URL:
POST https://sms-acktiwator.ru/api/webhook
Content-Type: application/x-www-form-urlencoded
key=YOUR_API_KEY&action=set&url=https://your-host.com/webhook
Response (200):
{
"webhook": {
"url": "https://your-host.com/webhook",
"is_active": true,
"is_enabled": true,
"has_secret": true,
"auto_disabled_at": null,
"consecutive_failures": 0
}
}
The signing secret is returned once, on rotate_secret:
{ "secret": "e3b0c44298fc1c149afbf4c8996fb924..." }
Errors: bad key — 403 BAD_KEY; webhooks disabled — 403 DISABLED; invalid URL — 400 BAD_URL; too many requests — 429 CHANNEL_LIMIT (mutations: 20/min).
Push request structure
We send a POST to your URL with Content-Type: application/json and these headers:
| Header | Description |
|---|---|
X-Turbon-Event | Event type: sms.received or otp.code |
X-Turbon-Delivery | Event id (use it for deduplication) |
X-Turbon-Signature | Signature: t=<unix>,v1=<HMAC-SHA256> |
User-Agent | turbon-rent-webhooks/1.0 |
Common envelope:
{
"event": "sms.received",
"id": "3f9a1c2b4d5e6f708192a3b4c5d6e7f8",
"created_at": "2026-07-11T10:15:30Z",
"api_version": "2026-07-11",
"data": { ... }
}
data for sms.received:
{
"rental_id": 1000000123,
"phone": "+48123456789",
"from": "Google",
"text": "G-123456 is your code",
"received_at": "2026-07-11T10:15:29Z"
}
| Field | Type | Description |
|---|---|---|
rental_id | int|null | Rental ID (same as Numbers API). null for offline rentals. |
phone | string | Your receiving number |
from | string | SMS sender |
text | string | Message text |
received_at | string | ISO-8601 UTC receive time |
data for otp.code:
{
"activation_id": 456,
"phone": "+79991234567",
"service": "telegram",
"country": "ru",
"code": "123456",
"received_at": "2026-07-11T10:15:29Z"
}
| Field | Type | Description |
|---|---|---|
activation_id | int | Activation ID (same one returned by getNumber in the OTP API: ACCESS_NUMBER:<activation_id>:<phone>) |
phone | string | Activation number |
service | string | Service code |
country | string | Country ISO |
code | string | Received code |
received_at | string | ISO-8601 UTC |
Verifying the signature
The X-Turbon-Signature header has the form t=<unix>,v1=<hex>. To verify:
- Take the raw request body (bytes as received) and the
tvalue. - Compute
HMAC-SHA256(secret, "<t>.<raw_body>")in hex and compare tov1(constant-time). - Reject the request if
|now − t| > 5 minutes(replay protection).
Example (Python):
import hmac, hashlib, time
def verify(secret, header, raw_body):
parts = dict(p.split('=', 1) for p in header.split(','))
t, v1 = parts['t'], parts['v1']
if abs(time.time() - int(t)) > 300:
return False
expected = hmac.new(secret.encode(), f"{t}.{raw_body}".encode(),
hashlib.sha256).hexdigest()
return hmac.compare_digest(expected, v1)
Delivery, retries and idempotency
- Respond
2xxwithin 10 seconds to acknowledge. - Non-2xx or timeout → retried with increasing delay: ≈1m, 5m, 15m, 1h, 3h, 6h, 12h (up to 8 attempts, ~22 hours), then the event is dropped.
- Delivery is at-least-once: an event may arrive more than once (e.g. if your
2xxdid not reach us). Deduplicate on theidfield (also sent asX-Turbon-Delivery). - After 20 consecutive fully-failed events the webhook is auto-disabled; re-enable it via
set. - Service/technical SMS are not pushed.