{"openapi":"3.1.0","info":{"title":"VARGO Partner API","version":"1.0","description":"REST API для продажи VPN в своём боте, мини-аппе или на сайте: тарифы, счета, клиенты и их устройства. Клиент платит платформе, наценка партнёра начисляется на его баланс.\n\nКлюч партнёра — в заголовке `Authorization: Bearer vgo_live_…`, его выдаёт платформа. Ключ живёт только на сервере партнёра: в коде мини-аппа или сайта его быть не должно. Деньги — строки в рублях (`\"150.00\"`), даты — ISO-8601 UTC. Ошибки — `{error: {code, message, fields}}`: ветвиться по `code`, `message` клиенту не показывать."},"servers":[{"url":"https://api.vargopartners.com"}],"paths":{"/api/partner/v1/account":{"get":{"tags":["Partner API"],"summary":"Аккаунт партнёра","description":"Название сервиса, наценка и включён ли пробный период. Удобная первая проверка ключа: неверный ключ — `401 UNAUTHORIZED`.","operationId":"get_account_api_partner_v1_account_get","responses":{"200":{"description":"Аккаунт партнёра","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiAccount"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/plans":{"get":{"tags":["Partner API"],"summary":"Тарифы","description":"Тарифы и доп. устройства с ценами для клиента: цена платформы плюс наценка партнёра, та же формула во всех каналах продаж. `plan_id` отсюда передаётся в `POST /payments`.","operationId":"get_plans_api_partner_v1_plans_get","responses":{"200":{"description":"Тарифы с ценами","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPlans"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/payment-methods":{"get":{"tags":["Partner API"],"summary":"Способы оплаты","description":"Способы, доступные клиенту прямо сейчас; `method` отсюда передаётся в `POST /payments`. Список меняется — перечитывайте его перед показом клиенту.","operationId":"get_payment_methods_api_partner_v1_payment_methods_get","responses":{"200":{"description":"Способы оплаты","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPaymentMethods"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/apps":{"get":{"tags":["Partner API"],"summary":"VPN-приложения","description":"Для экрана «Как подключиться»: платформы, приложения со ссылками на установку и рекомендованное приложение. `app_id` совпадает с `subscription.connect[].app_id` клиента. Подписи — на языке из `Accept-Language` (`ru` или `en`, без заголовка — `en`).","operationId":"get_apps_api_partner_v1_apps_get","responses":{"200":{"description":"Приложения и ссылки на установку","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiApps"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/documents":{"get":{"tags":["Partner API"],"summary":"Документы клиента","description":"Ссылки на пользовательское соглашение и политику конфиденциальности под названием сервиса партнёра. Показывайте их клиенту до оплаты. Текст ведёт платформа, страницы открываются без ключа; заголовки — на языке из `Accept-Language`.","operationId":"get_documents_api_partner_v1_documents_get","responses":{"200":{"description":"Ссылки на документы","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiDocuments"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/clients":{"get":{"tags":["Partner API"],"summary":"Список клиентов","description":"Клиенты партнёра постранично, свежие первыми. Фильтр `status` — по подписке: `active`, `expired`, `suspended` — как `subscription.status`; `none` — подписки не было ни разу.","operationId":"list_clients_api_partner_v1_clients_get","parameters":[{"name":"page","in":"query","required":false,"schema":{"type":"integer","maximum":100000,"minimum":1,"description":"Номер страницы, с 1","default":1,"title":"Page"},"description":"Номер страницы, с 1"},{"name":"limit","in":"query","required":false,"schema":{"type":"integer","maximum":100,"minimum":1,"description":"Клиентов на странице, до 100","default":20,"title":"Limit"},"description":"Клиентов на странице, до 100"},{"name":"status","in":"query","required":false,"schema":{"anyOf":[{"enum":["active","expired","suspended","none"],"type":"string"},{"type":"null"}],"description":"Статус подписки; без фильтра — все клиенты","title":"Status"},"description":"Статус подписки; без фильтра — все клиенты"}],"responses":{"200":{"description":"Страница клиентов","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiClientsPage"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/clients/{client_id}":{"get":{"tags":["Partner API"],"summary":"Клиент","description":"Статус и срок подписки, ссылка подписки и готовые ссылки подключения. Клиент появляется с первым счётом или пробным периодом, до этого — `404 API_CLIENT_NOT_FOUND`. Клиент, заблокированный платформой, — `403 API_CLIENT_BLOCKED` на всех ручках клиента.","operationId":"get_client_api_partner_v1_clients__client_id__get","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9._:@+-]*[A-Za-z0-9_:@+-][A-Za-z0-9._:@+-]*$","description":"Id клиента в вашей системе","title":"Client Id"},"description":"Id клиента в вашей системе"}],"responses":{"200":{"description":"Клиент","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiClient"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/clients/{client_id}/trial":{"post":{"tags":["Partner API"],"summary":"Пробный период","description":"Выдаёт пробный период, если он включён партнёру (`trial_enabled` в `GET /account`). Клиента нет — заводится. Ответ — клиент со ссылкой подписки. Отказы: `403 TRIAL_DISABLED`; `409 TRIAL_ALREADY_USED` — у клиента уже была подписка; `429 TRIAL_DAILY_LIMIT` — исчерпан суточный лимит партнёра; `503 SERVICE_UNAVAILABLE` — пробный период не выдан, запрос можно повторить.","operationId":"start_trial_api_partner_v1_clients__client_id__trial_post","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9._:@+-]*[A-Za-z0-9_:@+-][A-Za-z0-9._:@+-]*$","description":"Id клиента в вашей системе","title":"Client Id"},"description":"Id клиента в вашей системе"}],"responses":{"200":{"description":"Клиент с пробной подпиской","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiClient"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/clients/{client_id}/rotate-link":{"post":{"tags":["Partner API"],"summary":"Перевыпустить ссылку подписки","description":"Новая ссылка подписки; старая сразу перестаёт работать, и клиент добавляет подписку в приложение заново. Не чаще раза в час на клиента: иначе `429 LINK_ROTATE_TOO_SOON`, пауза в секундах — в заголовке `Retry-After`. Без действующей подписки — `400 NO_ACTIVE_SUBSCRIPTION`.","operationId":"rotate_link_api_partner_v1_clients__client_id__rotate_link_post","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9._:@+-]*[A-Za-z0-9_:@+-][A-Za-z0-9._:@+-]*$","description":"Id клиента в вашей системе","title":"Client Id"},"description":"Id клиента в вашей системе"}],"responses":{"200":{"description":"Клиент с новой ссылкой","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiClient"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/clients/{client_id}/devices":{"get":{"tags":["Partner API"],"summary":"Устройства клиента","description":"Подключённые устройства и лимит. Без подписки список пуст. Если платформа не ответила — `503 SERVICE_UNAVAILABLE`, а не пустой список: пустой ответ всегда значит «устройств нет».","operationId":"list_devices_api_partner_v1_clients__client_id__devices_get","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9._:@+-]*[A-Za-z0-9_:@+-][A-Za-z0-9._:@+-]*$","description":"Id клиента в вашей системе","title":"Client Id"},"description":"Id клиента в вашей системе"}],"responses":{"200":{"description":"Устройства и лимит","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiDevices"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/clients/{client_id}/devices/{device_id}":{"delete":{"tags":["Partner API"],"summary":"Удалить устройство","description":"Отключает устройство и освобождает место под новое. `device_id` — из `GET …/devices`, в пути URL-кодированный. Ответ — обновлённый список, как у `GET`. Такого устройства нет — `404 DEVICE_NOT_FOUND`.","operationId":"delete_device_api_partner_v1_clients__client_id__devices__device_id__delete","parameters":[{"name":"client_id","in":"path","required":true,"schema":{"type":"string","minLength":1,"maxLength":128,"pattern":"^[A-Za-z0-9._:@+-]*[A-Za-z0-9_:@+-][A-Za-z0-9._:@+-]*$","description":"Id клиента в вашей системе","title":"Client Id"},"description":"Id клиента в вашей системе"},{"name":"device_id","in":"path","required":true,"schema":{"type":"string","description":"HWID устройства из `GET …/devices`, URL-кодированный","title":"Device Id"},"description":"HWID устройства из `GET …/devices`, URL-кодированный"}],"responses":{"200":{"description":"Устройства после удаления","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiDevices"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/payments":{"post":{"tags":["Partner API"],"summary":"Выставить счёт","description":"Счёт на подписку (`purpose: subscription` и `plan_id`) или на доп. устройства (`purpose: devices` и `devices`). Клиента нет — заводится. Продление — тот же вызов на тот же `client_id`: срок прибавляется к текущему, ссылка подписки не меняется. Ссылку `payment_url` отдайте клиенту, результат оплаты — `GET /payments/{payment_id}`.\n\nЗаголовок `Idempotency-Key` обязателен — обычно номер заказа в вашей системе. `201` — счёт выставлен; `200` — повтор с тем же ключом и теми же полями, в ответе тот же счёт и `replayed: true`; `409 IDEMPOTENCY_KEY_REUSE` — ключ уже занят счётом с другими полями; `409 OPERATION_IN_PROGRESS` — счёт по этому ключу ещё выставляется, повторите тем же ключом через пару секунд; `503 PAYMENT_UNAVAILABLE` — счёт не выставлен, повторите тем же ключом.","operationId":"create_payment_api_partner_v1_payments_post","parameters":[{"name":"Idempotency-Key","in":"header","required":true,"schema":{"type":"string","minLength":1,"maxLength":200,"title":"Idempotency-Key"},"description":"Ключ повтора, обычно номер заказа в вашей системе, до 200 символов. Повтор с тем же ключом и теми же полями не выставит второй счёт. Нет ключа — `400 IDEMPOTENCY_KEY_REQUIRED`, длиннее — `400 IDEMPOTENCY_KEY_TOO_LONG`"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPaymentCreate"}}}},"responses":{"201":{"description":"Счёт выставлен","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPaymentCreated"}}}},"200":{"description":"Повтор по тому же `Idempotency-Key`: счёт первого запроса, `replayed: true`","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPaymentCreated"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}},"/api/partner/v1/payments/{payment_id}":{"get":{"tags":["Partner API"],"summary":"Счёт","description":"Текущее состояние счёта; после оплаты в `client` — клиент со ссылкой подписки. Это источник истины: перед выдачей доступа у себя перечитайте счёт. `expired` не окончательный — поздняя оплата переводит счёт в `succeeded`.","operationId":"get_payment_api_partner_v1_payments__payment_id__get","parameters":[{"name":"payment_id","in":"path","required":true,"schema":{"type":"string","format":"uuid","description":"Id счёта из ответа `POST /payments`","title":"Payment Id"},"description":"Id счёта из ответа `POST /payments`"}],"responses":{"200":{"description":"Счёт","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiPayment"}}}},"401":{"description":"Ключ не принят: `UNAUTHORIZED`. Неверный и отозванный ключ, выключенный доступ к API — один ответ","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"422":{"description":"Запрос не прошёл проверку: `code` — `VALIDATION_ERROR`, в `fields` — поле и причина","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}},"429":{"description":"Превышен лимит: `RATE_LIMITED` — повторить после паузы из `Retry-After`. У суточных лимитов (`NEW_CLIENTS_DAILY_LIMIT`, `TRIAL_DAILY_LIMIT`) заголовка нет — повторять на следующие сутки","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}},"headers":{"Retry-After":{"description":"Пауза в секундах до повтора; есть у `RATE_LIMITED` и `LINK_ROTATE_TOO_SOON`","schema":{"type":"integer","minimum":1}}}},"default":{"description":"Ошибка — тот же конверт; ветвиться по `code`, список кодов — в документации","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApiError"}}}}}}}},"components":{"schemas":{"ApiAccount":{"properties":{"brand_name":{"type":"string","title":"Brand Name","description":"Название сервиса партнёра — его видит клиент в документах и в подписке"},"markup_percent":{"type":"string","title":"Markup Percent","description":"Наценка партнёра к цене платформы, %","examples":["50.00"]},"trial_enabled":{"type":"boolean","title":"Trial Enabled","description":"Пробный период через API включён"},"currency":{"type":"string","title":"Currency","description":"Валюта цен и сумм","examples":["RUB"]}},"type":"object","required":["brand_name","markup_percent","trial_enabled","currency"],"title":"ApiAccount"},"ApiApp":{"properties":{"app_id":{"type":"string","title":"App Id","description":"Код приложения","examples":["happ"]},"name":{"type":"string","title":"Name","description":"Название приложения","examples":["Happ"]},"downloads":{"additionalProperties":{"items":{"$ref":"#/components/schemas/ApiDownload"},"type":"array"},"type":"object","title":"Downloads","description":"Ссылки на установку по платформам: ключ — `platform_id`"}},"type":"object","required":["app_id","name","downloads"],"title":"ApiApp"},"ApiApps":{"properties":{"platforms":{"items":{"$ref":"#/components/schemas/ApiPlatform"},"type":"array","title":"Platforms","description":"Платформы в порядке показа"},"apps":{"items":{"$ref":"#/components/schemas/ApiApp"},"type":"array","title":"Apps","description":"VPN-приложения"},"recommended_app_id":{"type":"string","title":"Recommended App Id","description":"Приложение, которое советовать по умолчанию","examples":["happ"]}},"type":"object","required":["platforms","apps","recommended_app_id"],"title":"ApiApps"},"ApiClient":{"properties":{"client_id":{"type":"string","title":"Client Id","description":"Id клиента в вашей системе","examples":["user-42"]},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Когда клиент заведён, UTC"},"subscription":{"anyOf":[{"$ref":"#/components/schemas/ApiSubscription"},{"type":"null"}],"description":"Подписка; `null` — подписки не было ни разу"},"trial_available":{"type":"boolean","title":"Trial Available","description":"Пробный период сейчас можно выдать: подписки не было, пробный период включён партнёру, суточный лимит не исчерпан, клиент не заблокирован"}},"type":"object","required":["client_id","created_at","subscription","trial_available"],"title":"ApiClient"},"ApiClientsPage":{"properties":{"items":{"items":{"$ref":"#/components/schemas/ApiClient"},"type":"array","title":"Items","description":"Клиенты на странице"},"total":{"type":"integer","title":"Total","description":"Всего клиентов по фильтру"},"page":{"type":"integer","title":"Page","description":"Номер страницы"},"limit":{"type":"integer","title":"Limit","description":"Клиентов на странице"}},"type":"object","required":["items","total","page","limit"],"title":"ApiClientsPage"},"ApiConnectLink":{"properties":{"app_id":{"type":"string","title":"App Id","description":"Код приложения — как в `GET /apps`","examples":["happ"]},"app_name":{"type":"string","title":"App Name","description":"Название приложения","examples":["Happ"]},"connect_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Connect Url","description":"Адрес для кнопки «Открыть в приложении»: https-страница, которая открывает приложение с подпиской"},"qr_payload":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Qr Payload","description":"Строка для QR-кода: его сканирует приложение"},"supports_manual_url":{"type":"boolean","title":"Supports Manual Url","description":"Приложение принимает ссылку подписки, вставленную вручную"}},"type":"object","required":["app_id","app_name","connect_url","qr_payload","supports_manual_url"],"title":"ApiConnectLink"},"ApiDevice":{"properties":{"device_id":{"type":"string","title":"Device Id","description":"HWID устройства; в пути запроса — URL-кодированный"},"platform":{"type":"string","title":"Platform","description":"Платформа устройства","examples":["iOS"]},"model":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Model","description":"Модель устройства, если приложение её сообщило"},"os_version":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Os Version","description":"Версия ОС, если приложение её сообщило"},"created_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Created At","description":"Когда устройство подключилось впервые, UTC"}},"type":"object","required":["device_id","platform","model","os_version","created_at"],"title":"ApiDevice"},"ApiDevices":{"properties":{"devices":{"items":{"$ref":"#/components/schemas/ApiDevice"},"type":"array","title":"Devices","description":"Подключённые устройства"},"devices_count":{"type":"integer","title":"Devices Count","description":"Сколько устройств подключено"},"devices_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Devices Limit","description":"Сколько устройств можно подключить; `null` — без ограничения"}},"type":"object","required":["devices","devices_count","devices_limit"],"title":"ApiDevices"},"ApiDevicesOffer":{"properties":{"included":{"type":"integer","title":"Included","description":"Устройств входит в подписку"},"max":{"type":"integer","title":"Max","description":"Больше этого числа устройств у клиента быть не может"},"price":{"type":"string","title":"Price","description":"Цена одного доп. устройства для клиента","examples":["75.00"]},"platform_price":{"type":"string","title":"Platform Price","description":"Часть платформы за одно устройство","examples":["50.00"]},"partner_share":{"type":"string","title":"Partner Share","description":"Наценка партнёра за одно устройство","examples":["25.00"]}},"type":"object","required":["included","max","price","platform_price","partner_share"],"title":"ApiDevicesOffer"},"ApiDocument":{"properties":{"type":{"type":"string","enum":["terms_of_service","privacy_policy"],"title":"Type","description":"`terms_of_service` — пользовательское соглашение, `privacy_policy` — политика конфиденциальности"},"title":{"type":"string","title":"Title","description":"Заголовок документа на языке из `Accept-Language`"},"url":{"type":"string","title":"Url","description":"Открытая страница документа под названием сервиса партнёра"}},"type":"object","required":["type","title","url"],"title":"ApiDocument"},"ApiDocuments":{"properties":{"documents":{"items":{"$ref":"#/components/schemas/ApiDocument"},"type":"array","title":"Documents","description":"Документы клиента"}},"type":"object","required":["documents"],"title":"ApiDocuments"},"ApiDownload":{"properties":{"label":{"type":"string","title":"Label","description":"Подпись ссылки для клиента","examples":["App Store"]},"url":{"type":"string","title":"Url","description":"Ссылка на установку приложения"}},"type":"object","required":["label","url"],"title":"ApiDownload"},"ApiError":{"description":"Конверт любой ошибки: статус HTTP плюс `error.code`.","properties":{"error":{"$ref":"#/components/schemas/ApiErrorBody","description":"Код, текст и поля ошибки"}},"required":["error"],"title":"ApiError","type":"object"},"ApiErrorBody":{"properties":{"code":{"description":"Машиночитаемый код ошибки — ветвиться по нему","examples":["VALIDATION_ERROR"],"title":"Code","type":"string"},"message":{"description":"Текст для логов на языке из `Accept-Language` (`ru` или `en`); клиенту не показывать","title":"Message","type":"string"},"fields":{"anyOf":[{"additionalProperties":{"type":"string"},"type":"object"},{"type":"null"}],"description":"Поле → причина у `VALIDATION_ERROR`; у остальных ошибок `null`","title":"Fields"}},"required":["code","message","fields"],"title":"ApiErrorBody","type":"object"},"ApiPayment":{"properties":{"payment_id":{"type":"string","format":"uuid","title":"Payment Id","description":"Id счёта"},"status":{"type":"string","enum":["pending","succeeded","failed","expired"],"title":"Status","description":"`pending` — ждёт оплаты; `succeeded` — оплачен, доступ выдан; `expired` — срок оплаты вышел, но статус не окончательный: поздняя оплата переводит счёт в `succeeded`; `failed` — оплата не прошла, бывает и после `succeeded`, если банк отозвал платёж"},"purpose":{"type":"string","enum":["subscription","devices"],"title":"Purpose","description":"Что оплачивается"},"client_id":{"type":"string","title":"Client Id","description":"Id клиента в вашей системе","examples":["user-42"]},"plan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Plan Id","description":"Тариф — у `purpose: subscription`"},"devices":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Devices","description":"Сколько устройств — у `purpose: devices`"},"method":{"type":"string","title":"Method","description":"Способ оплаты","examples":["sbp"]},"amount":{"type":"string","title":"Amount","description":"Сумма к оплате клиентом","examples":["150.00"]},"platform_amount":{"type":"string","title":"Platform Amount","description":"Часть платформы","examples":["100.00"]},"partner_share":{"type":"string","title":"Partner Share","description":"Наценка партнёра: после оплаты ложится на его баланс","examples":["50.00"]},"currency":{"type":"string","title":"Currency","description":"Валюта","examples":["RUB"]},"payment_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Url","description":"Страница оплаты для клиента; есть только у `pending`"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Когда счёт выставлен, UTC"},"expires_at":{"type":"string","format":"date-time","title":"Expires At","description":"Ориентир срока оплаты, UTC: статус меняется с задержкой до часа, поздняя оплата проходит"},"paid_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paid At","description":"Когда счёт оплачен, UTC"},"client":{"anyOf":[{"$ref":"#/components/schemas/ApiClient"},{"type":"null"}],"description":"Клиент со ссылкой подписки; заполнен у `succeeded`"}},"type":"object","required":["payment_id","status","purpose","client_id","plan_id","devices","method","amount","platform_amount","partner_share","currency","payment_url","created_at","expires_at","paid_at","client"],"title":"ApiPayment"},"ApiPaymentCreate":{"properties":{"client_id":{"type":"string","maxLength":128,"minLength":1,"pattern":"^[A-Za-z0-9._:@+-]*[A-Za-z0-9_:@+-][A-Za-z0-9._:@+-]*$","title":"Client Id","description":"Id клиента в вашей системе: 1–128 символов `A–Z a–z 0–9 . _ : @ + -`, не `.` и не `..`, регистр различается. Нового клиента счёт заводит сам","examples":["user-42"]},"purpose":{"type":"string","enum":["subscription","devices"],"title":"Purpose","description":"`subscription` — подписка или её продление, `devices` — доп. устройства"},"plan_id":{"anyOf":[{"type":"integer","maximum":2147483647.0,"minimum":1.0},{"type":"null"}],"title":"Plan Id","description":"Id тарифа из `GET /plans` — только при `purpose: subscription`","examples":[3]},"devices":{"anyOf":[{"type":"integer","minimum":1.0},{"type":"null"}],"title":"Devices","description":"Сколько устройств добавить, от 1 — только при `purpose: devices`"},"method":{"type":"string","maxLength":32,"minLength":1,"title":"Method","description":"Способ оплаты из `GET /payment-methods`","examples":["sbp"]},"return_url":{"anyOf":[{"type":"string","maxLength":500},{"type":"null"}],"title":"Return Url","description":"Куда вернуть клиента после оплаты: только https, до 500 символов. Поддерживается не каждым способом оплаты"}},"additionalProperties":false,"type":"object","required":["client_id","purpose","method"],"title":"ApiPaymentCreate","description":"Тело `POST /payments`. Неизвестные поля отклоняются — `422 VALIDATION_ERROR`."},"ApiPaymentCreated":{"properties":{"payment_id":{"type":"string","format":"uuid","title":"Payment Id","description":"Id счёта"},"status":{"type":"string","enum":["pending","succeeded","failed","expired"],"title":"Status","description":"`pending` — ждёт оплаты; `succeeded` — оплачен, доступ выдан; `expired` — срок оплаты вышел, но статус не окончательный: поздняя оплата переводит счёт в `succeeded`; `failed` — оплата не прошла, бывает и после `succeeded`, если банк отозвал платёж"},"purpose":{"type":"string","enum":["subscription","devices"],"title":"Purpose","description":"Что оплачивается"},"client_id":{"type":"string","title":"Client Id","description":"Id клиента в вашей системе","examples":["user-42"]},"plan_id":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Plan Id","description":"Тариф — у `purpose: subscription`"},"devices":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Devices","description":"Сколько устройств — у `purpose: devices`"},"method":{"type":"string","title":"Method","description":"Способ оплаты","examples":["sbp"]},"amount":{"type":"string","title":"Amount","description":"Сумма к оплате клиентом","examples":["150.00"]},"platform_amount":{"type":"string","title":"Platform Amount","description":"Часть платформы","examples":["100.00"]},"partner_share":{"type":"string","title":"Partner Share","description":"Наценка партнёра: после оплаты ложится на его баланс","examples":["50.00"]},"currency":{"type":"string","title":"Currency","description":"Валюта","examples":["RUB"]},"payment_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Payment Url","description":"Страница оплаты для клиента; есть только у `pending`"},"created_at":{"type":"string","format":"date-time","title":"Created At","description":"Когда счёт выставлен, UTC"},"expires_at":{"type":"string","format":"date-time","title":"Expires At","description":"Ориентир срока оплаты, UTC: статус меняется с задержкой до часа, поздняя оплата проходит"},"paid_at":{"anyOf":[{"type":"string","format":"date-time"},{"type":"null"}],"title":"Paid At","description":"Когда счёт оплачен, UTC"},"client":{"anyOf":[{"$ref":"#/components/schemas/ApiClient"},{"type":"null"}],"description":"Клиент со ссылкой подписки; заполнен у `succeeded`"},"replayed":{"type":"boolean","title":"Replayed","description":"`true` — повтор по тому же `Idempotency-Key`: в ответе счёт, выставленный первым запросом"}},"type":"object","required":["payment_id","status","purpose","client_id","plan_id","devices","method","amount","platform_amount","partner_share","currency","payment_url","created_at","expires_at","paid_at","client","replayed"],"title":"ApiPaymentCreated"},"ApiPaymentMethod":{"properties":{"method":{"type":"string","title":"Method","description":"Код способа — передаётся в `POST /payments`","examples":["sbp"]},"title":{"type":"string","title":"Title","description":"Название способа для клиента","examples":["СБП"]}},"type":"object","required":["method","title"],"title":"ApiPaymentMethod"},"ApiPaymentMethods":{"properties":{"methods":{"items":{"$ref":"#/components/schemas/ApiPaymentMethod"},"type":"array","title":"Methods","description":"Способы оплаты, доступные клиенту сейчас"}},"type":"object","required":["methods"],"title":"ApiPaymentMethods"},"ApiPlan":{"properties":{"plan_id":{"type":"integer","title":"Plan Id","description":"Id тарифа — передаётся в `POST /payments`","examples":[3]},"months":{"type":"integer","title":"Months","description":"Срок тарифа в месяцах; у бессрочного смотрите `lifetime`","examples":[1]},"lifetime":{"type":"boolean","title":"Lifetime","description":"Бессрочный тариф"},"price":{"type":"string","title":"Price","description":"Цена для клиента — сумма счёта","examples":["150.00"]},"platform_price":{"type":"string","title":"Platform Price","description":"Часть платформы","examples":["100.00"]},"partner_share":{"type":"string","title":"Partner Share","description":"Наценка партнёра: после оплаты ложится на его баланс","examples":["50.00"]}},"type":"object","required":["plan_id","months","lifetime","price","platform_price","partner_share"],"title":"ApiPlan"},"ApiPlans":{"properties":{"currency":{"type":"string","title":"Currency","description":"Валюта цен","examples":["RUB"]},"plans":{"items":{"$ref":"#/components/schemas/ApiPlan"},"type":"array","title":"Plans","description":"Тарифы, которые сейчас продаются"},"devices":{"anyOf":[{"$ref":"#/components/schemas/ApiDevicesOffer"},{"type":"null"}],"description":"Условия докупки устройств; `null` — доп. устройства сейчас не продаются"}},"type":"object","required":["currency","plans","devices"],"title":"ApiPlans"},"ApiPlatform":{"properties":{"platform_id":{"type":"string","title":"Platform Id","description":"Код платформы — ключ в `downloads` приложения","examples":["ios"]},"name":{"type":"string","title":"Name","description":"Название платформы для клиента","examples":["iPhone"]}},"type":"object","required":["platform_id","name"],"title":"ApiPlatform"},"ApiSubscription":{"properties":{"status":{"type":"string","enum":["active","expired","suspended"],"title":"Status","description":"`active` — действует (у пробной `is_trial: true`); `expired` — срок вышел, продление возобновляет подписку с момента оплаты; `suspended` — срок идёт, но доступ приостановлен платформой"},"is_trial":{"type":"boolean","title":"Is Trial","description":"Пробная подписка"},"expires_at":{"type":"string","format":"date-time","title":"Expires At","description":"Конец срока, UTC"},"days_left":{"type":"integer","title":"Days Left","description":"Дней до конца срока с округлением вверх; у истёкшей — 0","examples":[30]},"subscription_url":{"anyOf":[{"type":"string"},{"type":"null"}],"title":"Subscription Url","description":"Ссылка подписки для VPN-приложения. Отдаётся и у истёкшей: после продления ссылка та же. `null` — ссылки пока нет"},"connect":{"items":{"$ref":"#/components/schemas/ApiConnectLink"},"type":"array","title":"Connect","description":"Готовые ссылки подключения по приложениям; пусто, пока нет ссылки подписки"},"devices_limit":{"anyOf":[{"type":"integer"},{"type":"null"}],"title":"Devices Limit","description":"Сколько устройств можно подключить; `null` — без ограничения"}},"type":"object","required":["status","is_trial","expires_at","days_left","subscription_url","connect","devices_limit"],"title":"ApiSubscription"}},"securitySchemes":{"PartnerKey":{"type":"http","scheme":"bearer","description":"Ключ партнёра `vgo_live_…`, его выдаёт платформа. Хранится только на сервере партнёра."}}},"security":[{"PartnerKey":[]}]}