Metadata-Version: 2.4
Name: sova-partner
Version: 0.1.0
Summary: Python SDK для партнёрского API SOVA VPN (ресейл VPN-серверов и конфигов)
Author: SOVA VPN
License: MIT
Project-URL: Homepage, https://partner.sova-vpn.online
Project-URL: Documentation, https://partner.sova-vpn.online
Project-URL: OpenAPI schema, https://api.sova-vpn.online/partner/v1/openapi.json
Keywords: sova,vpn,wireguard,reseller,api,sdk,partner
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Topic :: Internet
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Typing :: Typed
Requires-Python: >=3.8
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: httpx>=0.24
Dynamic: license-file

# sova-partner — Python SDK партнёрского API SOVA VPN

Тонкий синхронный клиент для ресейла VPN-серверов и конфигов через партнёрский API.

## Установка

```bash
pip install sova-partner
# или из исходников:
pip install ./partner_sdk
```

## Быстрый старт

```python
from sova_partner import SovaPartner

sova = SovaPartner("sova_live_…")          # sova_test_… — песочница (без списаний)

# каталог и цена
cat = sova.catalog()
print(sova.quote(pc=10, term_days=30)["prices"])

# заказать сервер и дождаться готовности (выдача 10 мин – 2 ч)
srv = sova.create_server(country="DE", pc=10, term_days=30)   # provider="inferno"/"ultahost" опц.
srv = sova.wait_for_server(srv["server_id"])

# выпустить конфиги
cfg = sova.issue_config(srv["server_id"], protocol="wireguard", name="ноутбук")
print(cfg["config"])                        # готовый .conf / URI

sova.rotate_config(cfg["config_id"])        # ротация ключей
sova.revoke_config(cfg["config_id"])        # отзыв (hard-revoke)
sova.renew(srv["server_id"], term_days=30)  # продление
```

`Idempotency-Key` для `create_server` / `issue_config` / `renew` генерируется
автоматически (можно передать свой аргументом `idempotency_key`).

## Онбординг нового партнёра (без ключа)

```python
from sova_partner import Onboarding

ob = Onboarding()
r = ob.register(name="Моя компания", password="…")     # -> claim_token
ob.deposit(r["claim_token"], amount=50)                # -> pay_url (CryptoBot)
# ob.deposit_usdt(r["claim_token"], amount=50)         # или прямой USDT TRC20
api_key = ob.wait_for_key(r["claim_token"])            # после оплаты -> первый ключ (один раз!)
```

Первый ключ выдаётся после депозита ≥ min_deposit. Крупный первый депозит даёт
бонус на баланс (≥$300 +5% / ≥$1000 +10% / ≥$3000 +15%) и постоянную скидку.

## Вебхуки — проверка подписи

```python
from sova_partner import verify_signature

# во входящем HTTP-запросе от SOVA:
ok = verify_signature(
    secret=endpoint_secret,                       # выдан при create_webhook (один раз)
    signature_header=request.headers["X-Sova-Signature"],
    raw_body=request.body,                         # СЫРОЕ тело до JSON-парсинга
)
event    = request.headers["X-Sova-Event"]         # server.ready, config.created, deposit.paid, …
event_id = request.headers["X-Sova-Event-Id"]      # дедуп (доставка at-least-once)
```

События: `server.ready` / `server.failed` / `server.expiring`,
`config.created` / `config.revoked` / `config.rotated`, `deposit.paid`, `balance.low`.

## Ошибки

Все не-2xx поднимают исключение с `.status` и `.code` (машинный `detail`):

```python
from sova_partner import SovaError, SovaInsufficientBalance, SovaAuthError, SovaRateLimited

try:
    sova.create_server(country="DE", pc=10)
except SovaInsufficientBalance:      # 402
    ...
except SovaAuthError as e:           # 401/403 (invalid_key / insufficient_scope / ip_not_allowed)
    print(e.code)
except SovaRateLimited:              # 429
    ...
except SovaError as e:               # прочее (409 idempotency_key_reused, 404, …)
    print(e.status, e.code)
```

## Права ключа (scopes)

`catalog:read`, `balance:read`, `vpn:read`, `vpn:issue`, `vpn:revoke`,
`account:manage`. Управление ключами/вебхуками/депозитами/тикетами требует
`account:manage` (в дефолтные ключи не входит — используйте вход в ЛК или ключ
с этим правом). Ключ можно ограничить по IP (`ip_allowlist`).

Базовый URL по умолчанию: `https://api.sova-vpn.online/partner/v1`
(меняется параметром `base_url`).
