База всех примеров: https://premium.roxera.net. CORS открыт (allowlist на сервере). Формат — JSON. Email всегда в нижнем регистре.
Работает на любом стеке: 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'.
| Метод | Путь | Что делает |
|---|---|---|
| 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,...}}
/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", ...}
/v1/premium/link-code Bearer ID-tokencurl -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: новая привязка отвязывает старую.
/v1/premium/link Bearer ID-token# {"ok":true,"email":"...","linked":{"telegramId":123,"linkedAt":"..."} | null}
/v1/premium/unlink Bearer ID-token# {"ok":true,"email":"...","linked":null} — грант сохраняется, можно привязать другой TG
POST /verify тоже отдаёт поле linked — кабинет показывает привязку и кнопку «Обновить статус».
/v1/premium/cryptoinvoice Bearer ID-tokencurl -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}
/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 минут.
// При входе (уже есть 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=
| Команда | Что делает |
|---|---|
/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 с секретом — дёргать кроном).
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"}'
| Код | HTTP | Что значит |
|---|---|---|
bad_email | 400 | Пустой email в status/check |
unauthorized | 401 | Нет/протух Bearer или idToken |
forbidden | 403 | Чужой x-bot-secret на /internal/* |
rate_limited | 429 | Больше 5 crypto-счетов в час с IP |
not_configured | 500 | Нет CRYPTOBOT_TOKEN / BOT_TOKEN — деградированный режим |
invoice_failed | 502 | CryptoBot API не дал счёт |
Вебхук принимает и x-bot-secret, и штатный x-telegram-bot-api-secret-token.