API Premium-хаба https://premium.roxera.net

База всех примеров: https://premium.roxera.net. CORS открыт (allowlist на сервере). Формат — JSON. Email всегда в нижнем регистре.

0. Виджет «Вход RoxeraMail» — встройка за 2 строки

Работает на любом стеке: JS/TS, Python, PHP, Svelte, статика. Зависимостей нет.

<script src="https://premium.roxera.net/widget.js"
        data-api="https://premium.roxera.net" data-theme="dark"></script>
<div data-roxera-login></div>
// Слушаем вход:
RoxeraAuth.onLogin(function (u) {
  // u = { email, tier: 'free'|'premium', until, entitlements }
  if (u.tier === 'premium') unlockPro(u.entitlements);
});
// Текущий юзер / ручной логаут / код привязки TG:
RoxeraAuth.user(); RoxeraAuth.logout(); RoxeraAuth.linkCode();

События window: roxera:login, roxera:logout. Состояние: localStorage 'roxera.auth.v1'.

1. Публичные эндпоинты (без авторизации)

МетодПутьЧто делает
GET/v1/healthЖивость: {ok, service, ts}
GET/v1/premium/plansТариф: дни, $/Stars, ассеты, entitlements free/premium
GET/v1/premium/configПубличный конфиг виджета: firebaseWebKey, botUsername, флаги bot/crypto
GET/v1/premium/status?email=Бейдж тарифа: {email, tier, until?, entitlements}. Публичный — для UI, не для строгих проверок
curl 'https://premium.roxera.net/v1/premium/status?email=user@mail.roxera.net'
# {"email":"...","tier":"premium","until":"2026-10-29T...","entitlements":{"boxes":10,"dailyQuota":30,"verified":true,...}}

2. Строгая проверка (для своих бэкендов)

POST /v1/premium/verify

Клиент присылает свой Firebase ID token, сервер сам валидирует его в Google и отдаёт статус. Email из query брать нельзя — его можно подделать, токен — нет.

curl -X POST https://premium.roxera.net/v1/premium/verify \
  -H 'content-type: application/json' -d '{"idToken":"FIREBASE_ID_TOKEN"}'
# {"ok":true,"uid":"...","email":"...","tier":"premium","until":"...","entitlements":{...}}
// Python (свой бэкенд):
import urllib.request, json
body = json.dumps({"idToken": id_token_from_client}).encode()
r = urllib.request.urlopen("https://premium.roxera.net/v1/premium/verify", body)
print(json.load(r))  # {"tier": "premium", ...}

3. Привязка Telegram

POST /v1/premium/link-code Bearer ID-token

curl -X POST https://premium.roxera.net/v1/premium/link-code \
  -H "authorization: Bearer FIREBASE_ID_TOKEN" -H 'content-type: application/json' -d '{}'
# {"ok":true,"code":"123456"}  — живёт 10 минут

Дальше юзер шлёт боту /start 123456 → сервер связывает email ↔ telegramId (грант при этом не затирается). Один действующий Telegram: новая привязка отвязывает старую.

GET /v1/premium/link Bearer ID-token

# {"ok":true,"email":"...","linked":{"telegramId":123,"linkedAt":"..."} | null}

POST /v1/premium/unlink Bearer ID-token

# {"ok":true,"email":"...","linked":null} — грант сохраняется, можно привязать другой TG

POST /verify тоже отдаёт поле linked — кабинет показывает привязку и кнопку «Обновить статус».

4. Оплата CryptoBot (с сайта)

POST /v1/premium/cryptoinvoice Bearer ID-token

curl -X POST https://premium.roxera.net/v1/premium/cryptoinvoice \
  -H "authorization: Bearer FIREBASE_ID_TOKEN" -H 'content-type: application/json' \
  -d '{"asset":"USDT"}'   # или TON
# {"ok":true,"payUrl":"https://t.me/CryptoBot?...","invoice_id":123}

GET /v1/premium/check?email=

curl 'https://premium.roxera.net/v1/premium/check?email=user@mail.roxera.net'
# {"ok":true,"paid":true,"until":"..."} — грант уже выдан
# {"ok":true,"paid":false,"status":"active"} — ждём оплату

Лимит: 5 счетов в час с IP. Счёт живёт ~65 минут.

5. Почта: плотная интеграция (пример для roxera-mail)

// При входе (уже есть refreshPremiumFromServer):
const s = await fetch(API + '/v1/premium/status?email=' + email).then(r => r.json());
boxes   = s.entitlements.boxes;        // free 1 / premium 10
quota   = s.entitlements.dailyQuota;   // free 10 / premium 30
verified= s.entitlements.verified;     // галочка только если true С СЕРВЕРА
premiumDomains = s.entitlements.premiumDomains; // ['xye-coc.online','xyeglot.online']
// Строгий путь (рекомендуется): POST /verify с ID token вместо ?email=

6. Telegram-бот

КомандаЧто делает
/start 123456Привязка email по коду из кабинета (старый TG отвязывается)
/premiumМеню оплаты: Stars / USDT / TON (активным показывает срок)
/statusСтатус привязанного email
/unlinkОтвязка TG, грант сохраняется

Stars: sendInvoice XTR → pre_checkout_query → successful_payment → грант на привязанный email. CryptoBot: оплата → «Проверить» → грант сразу, даже если оплата была до привязки (заберётся при /start). Напоминания: за 3 и 1 день (POST /internal/remind с секретом — дёргать кроном).

7. Админка (секрет x-bot-secret)

curl -X POST https://premium.roxera.net/internal/admin/grant \
  -H 'x-bot-secret: SECRET' -H 'content-type: application/json' \
  -d '{"email":"user@mail.roxera.net","days":30,"via":"admin:restore"}'
curl -X POST https://premium.roxera.net/internal/admin/revoke \
  -H 'x-bot-secret: SECRET' -H 'content-type: application/json' \
  -d '{"email":"user@mail.roxera.net"}'

8. Ошибки и лимиты

КодHTTPЧто значит
bad_email400Пустой email в status/check
unauthorized401Нет/протух Bearer или idToken
forbidden403Чужой x-bot-secret на /internal/*
rate_limited429Больше 5 crypto-счетов в час с IP
not_configured500Нет CRYPTOBOT_TOKEN / BOT_TOKEN — деградированный режим
invoice_failed502CryptoBot API не дал счёт

Вебхук принимает и x-bot-secret, и штатный x-telegram-bot-api-secret-token.