Запуск продаж VPN через API: от ключа до первой подписки

Путь от ключа до первой подписки, которая открывается в VPN-приложении: какие запросы отправить, в каком порядке и что сохранить у себя.

Содержание 8 разделов
  1. Что сохранить на своей стороне
  2. Шаг первый: ключ и депозит
  3. Шаг второй: тарифы
  4. Шаг третий: пробный период
  5. Шаг четвёртый: платная подписка
  6. Шаг пятый: продление и события
  7. Сколько это занимает
  8. Чек-лист

Чтобы продавать VPN со своего сайта, из бота или биллинга, от платформы нужны ключ и депозит, а с вашей стороны хранилище пользователей и один обработчик HTTP. Прототип с первой подпиской собирается за вечер, рабочая интеграция с продлениями и разбором отказов занимает несколько дней.

событиеКабинет VPN APIключ, депозит, секрет вебхука
1GET /plansтарифы и закупочные цены
2POST /subscriptions/trialпроверка без денег
3POST /subscriptionsплатная подписка
4PUT /webhookсобытия о сроке

#Что сохранить на своей стороне

  • external_user_id: ваш идентификатор человека. Один человек это один id, подписок у него может быть несколько.
  • custom_id: ваш идентификатор операции, новый на каждую покупку и каждое продление. Сохраните его к заказу до отправки запроса.
  • subscription_id и subscription_url из ответа: по первому идут все дальнейшие вызовы, второй вы отдаёте пользователю.

#Шаг первый: ключ и депозит

Ключ выпускается в кабинете VPN API, раздел «Ключ и вебхук». Он показывается один раз, потом виден только префикс. Ключ тратит деньги депозита, поэтому храните его в переменной окружения на сервере: в браузер и приложение он попадать не должен.

Кабинет VPN API: активный ключ, адрес вебхука, выбор событий и тестовая отправка
Кабинет VPN API, «Ключ и вебхук». Демо-данные.

Депозит пополняется в том же кабинете или запросом POST /deposit. Все суммы в API идут в долларах парой: *_minor в центах для расчётов и *_usd строкой для показа. Лимит 60 запросов в минуту на ключ.

#Шаг второй: тарифы

GET /api/v1/vpn/plans
curl https://api.relayhub.surf/api/v1/vpn/plans \
  -H "Authorization: Bearer $VPN_API_KEY"
Значения примерные, из справочника. Метод: GET /plans.

price_minor это ваша закупка, её и спишут с депозита. Розничную цену вы считаете у себя. Кешировать тарифы дольше часа справочник не советует: цена может измениться, а продажа по устаревшей уходит в минус.

#Шаг третий: пробный период

Первой выдайте пробную подписку. Она бесплатная, один раз на external_user_id, и проверяет всю цепочку: запрос, ответ, ссылку в VPN-приложении. Если пробный период выключен в кабинете, придёт отказ trial_disabled.

POST /api/v1/vpn/subscriptions/trial
curl -X POST https://api.relayhub.surf/api/v1/vpn/subscriptions/trial \
  -H "Authorization: Bearer $VPN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"external_user_id": "user-42",
       "custom_id": "11111111-1111-4111-8111-111111111111"}'
В ответе charged_minor: 0 и подписка с is_trial: true. Метод: POST /subscriptions/trial.

#Шаг четвёртый: платная подписка

Перед покупкой проверьте остаток: GET /balance отдаёт spendable_minor, он должен покрывать price_minor тарифа. Делайте это до того, как покупатель заплатил вам.

POST /api/v1/vpn/subscriptions
curl -X POST https://api.relayhub.surf/api/v1/vpn/subscriptions \
  -H "Authorization: Bearer $VPN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"custom_id": "22222222-2222-4222-8222-222222222222",
       "plan_uuid": "550e8400-e29b-41d4-a716-446655440000",
       "external_user_id": "user-42"}'
Ответ сокращён, полный состав на странице POST /subscriptions.

subscription_url пользователь вставляет в VPN-приложение. При продлении и смене тарифа ссылка не меняется. Если у человека есть Telegram, передайте telegram_id и bot_id своего бота: подписка появится и в мини-аппе бота.

Если ответ не пришёл (таймаут, 500 или 503 upstream_unavailable), повторите запрос с тем же custom_id: вернётся та же подписка с idempotent_replay: true, второго списания не будет.

Отказы при покупке подписки
КодHTTPЧто значитПовторять
insufficient_balance402на депозите не хватает денег, подписка не созданапосле пополнения
forbidden403bot_id принадлежит другому аккаунтунет, проверьте bot_id
plan_not_found404тариф не найден или недоступеннет, возьмите plan_uuid из /plans
custom_id_conflict409этот custom_id уже был с другими параметраминет, нужен новый custom_id
operation_in_progress409первая попытка с этим custom_id ещё идётда, через секунду
external_user_conflict409telegram_id уже привязан к другому external_user_idнет, возьмите прежний external_user_id
rate_limited429больше 60 запросов в минутуда, через Retry-After
upstream_unavailable503сеть VPN временно недоступнада, с тем же custom_id

#Шаг пятый: продление и события

Продление на период тарифа идёт запросом POST /subscriptions/{id}/renew, на своё число дней от 3 до 1095 через renew-custom. У каждого продления свой новый custom_id.

Узнавать о конце срока удобнее событием, чем опросом. Задайте адрес в кабинете или запросом PUT /webhook:

PUT /api/v1/vpn/webhook
{
  "url": "https://example.com/vpn-webhook",
  "events": [
    "subscription.expires_in_24h",
    "subscription.expired",
    "deposit.credited"
  ]
}
Тело запроса. events: null подписывает на все события, включая будущие.

Как проверять подпись события и не продлить подписку дважды, читайте в статье про вебхуки и продления.

#Сколько это занимает

Прототип с первой подпиской собирается за вечер вместе с чтением справочника. Рабочая интеграция занимает несколько дней, и большая часть этого времени уходит на ваш продукт: витрину, оплату, письма и тексты на отказы. Если код пишет нейросеть, дайте ей спецификацию целиком; что ещё ей нужно знать, есть в статье про интеграцию руками агента.

#Чек-лист

Следующий шаг

Первая подписка без денег

Пробный период через API депозит не списывает. Выпустите ключ в кабинете VPN API и прогоните цепочку бесплатно.

Читать дальше

Вебхуки и повторы: как не потерять деньги на продлениях

Как принимать события и не продлить подписку дважды.

VPN · APIИнтеграция6 мин
Продажа VPN через API: свой сайт вместо готового бота

Когда своя интеграция вообще нужна.

VPN · APIИнтеграция3 мин
Интеграция платного API руками нейросети: что дать агенту и где он сожжёт депозит

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

APIИнтеграция3 мин
Собираем анонимную аналитику посещений. Подробнее