/api/v1/vpn/subscriptionsСписывает цену тарифа с депозита и выдаёт подписку. В ответе subscription_url:
её вы отдаёте пользователю, он вставляет ссылку в VPN-клиент.
Один external_user_id может иметь несколько подписок. Повтор с тем же custom_id
вернёт ту же подписку с idempotent_replay: true.
curl -X POST https://api.relayhub.surf/api/v1/vpn/subscriptions \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"external_user_id": "user-42",
"custom_id": "11111111-1111-4111-8111-111111111111",
"plan_uuid": "550e8400-e29b-41d4-a716-446655440000"
}'{
"success": true,
"custom_id": "11111111-1111-4111-8111-111111111111",
"subscription": {
"subscription_id": "01a06315-1270-705a-8d4c-58fea607bf2c",
"external_user_id": "user-42",
"plan_uuid": "550e8400-e29b-41d4-a716-446655440000",
"plan_name": "Standart 30d",
"is_trial": false,
"status": "active",
"subscription_url": "https://api.relayhub.surf/sub/wnT9NRf0Zk6McRRnp2nggc3K",
"days": 30,
"days_left": 30,
"devices": 2,
"auto_renew": false,
"renewal_count": 0,
"created_at": "2026-09-02T12:00:00Z",
"end_date": "2026-10-02T12:00:00Z",
"price_minor": 450,
"price_usd": "4.50"
},
"charged_minor": 450,
"charged_usd": "4.50",
"balance_after_minor": 11600,
"balance_after_usd": "116.00"
}Заголовок Authorization: Bearer <ключ> на каждом запросе. Ключ один на аккаунт, выпускается в кабинете партнёра и показывается один раз. Он тратит депозит: держите его на сервере.
external_user_idstringобязательноИдентификатор пользователя в вашей системе. Один человек = один id.
telegram_idinteger | nullнеобязательноTelegram id пользователя. Если задан, подписка появится у него в мини-аппе вашего бота (укажите bot_id) и он получит уведомления бота.
bot_iduuid | nullнеобязательноВаш бот из кабинета, к которому привязать пользователя. Только вместе с telegram_id.
custom_idstringобязательноВаш идентификатор операции, уникальный в рамках аккаунта. Повтор запроса с тем же custom_id вернёт результат первой попытки без повторного списания.
plan_uuiduuidобязательноТариф из GET /plans.
successbooleanобязательноcustom_idstringобязательноsubscriptionobjectобязательноcharged_minorintegerобязательноcharged_usdstringобязательноbalance_after_minorintegerобязательноbalance_after_usdstringобязательно401unauthorized: Неверный или отсутствующий API-ключ402insufficient_balance: Недостаточно средств на депозите403forbidden: Объект принадлежит другому аккаунту; api_disabled: Доступ к API для этого аккаунта закрыт404plan_not_found: Тариф не найден или недоступен409custom_id_conflict: Этот custom_id уже использован с другими параметрами; operation_in_progress: Операция с этим custom_id ещё выполняется; external_user_conflict: telegram_id уже привязан к другому external_user_id422validation_error: Неверные параметры запроса429rate_limited: Слишком много запросов503upstream_unavailable: Поставщик VPN временно недоступенcurl -X POST https://api.relayhub.surf/api/v1/vpn/subscriptions \
-H "Authorization: Bearer <YOUR_API_KEY>" \
-H "Content-Type: application/json" \
-d '{
"external_user_id": "user-42",
"custom_id": "11111111-1111-4111-8111-111111111111",
"plan_uuid": "550e8400-e29b-41d4-a716-446655440000"
}'{
"success": true,
"custom_id": "11111111-1111-4111-8111-111111111111",
"subscription": {
"subscription_id": "01a06315-1270-705a-8d4c-58fea607bf2c",
"external_user_id": "user-42",
"plan_uuid": "550e8400-e29b-41d4-a716-446655440000",
"plan_name": "Standart 30d",
"is_trial": false,
"status": "active",
"subscription_url": "https://api.relayhub.surf/sub/wnT9NRf0Zk6McRRnp2nggc3K",
"days": 30,
"days_left": 30,
"devices": 2,
"auto_renew": false,
"renewal_count": 0,
"created_at": "2026-09-02T12:00:00Z",
"end_date": "2026-10-02T12:00:00Z",
"price_minor": 450,
"price_usd": "4.50"
},
"charged_minor": 450,
"charged_usd": "4.50",
"balance_after_minor": 11600,
"balance_after_usd": "116.00"
}