охват

API Охвата

Совместим со стандартом SMM Panel API v2.

Клиент, написанный под другую панель этого стандарта, работает с нами без правок кода — меняются только адрес и ключ.

Адрес и ключ

POST https://api.ohvat.ru/api/v2

Один адрес на весь API. Что делать — говорит параметр action, а не путь.

Ключ берётся в кабинете, раздел «API». Он приезжает параметром key в каждом запросе.

Выглядит так: ohv_ и ещё 43 символа, всего 47. Показывается один раз, при выдаче — восстановить его мы не можем, только выпустить новый.

GET тоже разрешён — этого требует стандарт.

Ловушка: при GET ключ уезжает в строку адреса. Мы не пишем её в журнал доступа, но её пишут прокси и браузеры на стороне клиента. Для рабочих ключей используйте POST.

Формат запроса

Три формы, любая на выбор:

Форма (application/x-www-form-urlencoded) — так делает большинство готовых клиентов.

JSON — заголовок Content-Type должен содержать application/json, иначе тело не разбирается.

Строка запроса — работает и с POST, и с GET.

Ответ всегда JSON.

Валюта одна — рубли. Все денежные значения приезжают строками: "120.50", а не 120.5. Дробное JSON-число разбирается через double, и цена перестала бы совпадать с нашей до копейки.

Действия

services — список услуг

curl -X POST https://api.ohvat.ru/api/v2 \
  -d key=ВАШ_КЛЮЧ \
  -d action=services
[
  {
    "service": "7f3a1c20-0b9e-4a1f-9c33-6d2b8e5a1010",
    "name": "Telegram — просмотры",
    "category": "Telegram",
    "type": "Default",
    "rate": "18.00",
    "min": 100,
    "max": 500000,
    "refill": false,
    "cancel": false,
    "dripfeed": false
  }
]

service — идентификатор, который вы передаёте в add.

rate — цена за 1000 единиц.

min и max — границы количества в одном заказе.

balance — остаток на счёте

curl -X POST https://api.ohvat.ru/api/v2 \
  -d key=ВАШ_КЛЮЧ \
  -d action=balance
{"balance": "10000.00", "currency": "RUB"}

add — поставить заказ

curl -X POST https://api.ohvat.ru/api/v2 \
  -H 'Idempotency-Key: my-order-42' \
  -d key=ВАШ_КЛЮЧ \
  -d action=add \
  -d service=7f3a1c20-0b9e-4a1f-9c33-6d2b8e5a1010 \
  -d link=https://t.me/example \
  -d quantity=1000
{"order": "3b1d55a0-2e77-41c9-8a04-9f0c6b2d7e31"}

Деньги списываются в момент ответа. Заказ уходит в работу сам.

Ловушка, и это главное место в документе. Заголовок Idempotency-Key необязателен — так устроен стандарт. Без него повторный add с теми же параметрами — это второй оплаченный заказ, а не повтор первого. Так и задумано: реселлер, который осознанно заказывает второй раз, должен получить второй заказ.

Передавайте Idempotency-Key (от 8 до 128 символов), если повтор возможен из-за таймаута или ретрая вашего кода. С ним второй вызов вернёт тот же заказ и не спишет денег.

status — состояние одного заказа

curl -X POST https://api.ohvat.ru/api/v2 \
  -d key=ВАШ_КЛЮЧ \
  -d action=status \
  -d order=3b1d55a0-2e77-41c9-8a04-9f0c6b2d7e31
{
  "charge": "18.00",
  "start_count": null,
  "status": "In progress",
  "remains": 400,
  "currency": "RUB"
}

remains — сколько ещё не доставлено.

start_count всегда null: мы не храним счётчик «сколько было до старта», а ноль на этом месте был бы неправдой числом.

multi_status — до 100 заказов за раз

curl -X POST https://api.ohvat.ru/api/v2 \
  -d key=ВАШ_КЛЮЧ \
  -d action=multi_status \
  -d orders=3b1d55a0-2e77-41c9-8a04-9f0c6b2d7e31,00000000-0000-0000-0000-000000000000
{
  "3b1d55a0-2e77-41c9-8a04-9f0c6b2d7e31": {
    "charge": "18.00",
    "start_count": null,
    "status": "Completed",
    "remains": 0,
    "currency": "RUB"
  },
  "00000000-0000-0000-0000-000000000000": {
    "error": "Incorrect order ID",
    "code": "INCORRECT_ORDER_ID"
  }
}

Одна плохая строка не роняет пачку: у каждого идентификатора свой ответ.

Больше 100 идентификаторов — отказ целиком, код TOO_MANY_IDS.

Значения status

Значение Что означает
Pending принят, ещё не начат
In progress идёт
Completed выполнен целиком
Partial доставлено меньше заказанного; разница уже вернулась на баланс
Canceled не выполнен; деньги вернулись на баланс

Регистр значим — сравнивайте строку буквально.

Отдельного значения «сломалось» нет: такой заказ приезжает как Canceled, и деньги за него возвращены.

Недовоз возвращается автоматически, отдельного запроса на возврат не требуется. Проверяйте баланс, а не только статус.

Ошибки

Тело ошибки одинаково всегда:

{"error": "Not enough funds", "code": "INSUFFICIENT_BALANCE"}

error — текст для человека, code — для программы. Читайте code: текст может измениться.

HTTP code Когда
400 BAD_REQUEST запрос не разобран
400 UNKNOWN_ACTION нет такого action
400 MISSING_PARAMETER не хватает обязательного параметра
400 TOO_MANY_IDS больше 100 заказов в multi_status
401 INVALID_KEY ключ не найден, отозван или аккаунт отключён
402 INSUFFICIENT_BALANCE не хватает денег на счёте
404 INCORRECT_ORDER_ID заказа нет или он не ваш
422 SERVICE_UNAVAILABLE услуги нет или она сейчас недоступна
422 QUANTITY_OUT_OF_RANGE количество вне minmax
429 RATE_LIMIT превышен предел частоты
500 INTERNAL_ERROR ошибка на нашей стороне

Чужой заказ отвечает тем же INCORRECT_ORDER_ID, что и несуществующий.

Пределы частоты

120 запросов в минуту на аккаунт.

20 неудачных попыток аутентификации в минуту с одного адреса. Успешный запрос обнуляет этот счётчик — за чужие промахи с общего адреса вы не платите.

При превышении приезжает 429 и заголовок Retry-After с числом секунд. Дождитесь его, а не повторяйте сразу: немедленный повтор мы читаем как перебор.

Ключ

Ключ выпускается и отзывается в кабинете.

Отзыв действует немедленно. Уже поставленные заказы продолжают выполняться и остаются видны — отзыв ключа не отменяет оплаченную работу.

Отключение аккаунта отзывает ключ вместе с ним.

Поддержка

Телеграм владельца — контакт указан в подвале сайта и в кабинете. Там же объявляется поломка, если она случится.