TOKEN PAY

API

Документация бесплатного и открытого API системы аутентификации. Интегрируйте единую систему идентификации в ваши сервисы и приложения через OAuth 2.0, REST API и SDK.

Base URL: https://id.tokenpay.space/api/v1

API использует JSON для всех запросов и ответов. Все запросы должны содержать заголовок Content-Type: application/json.

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

Для начала работы с API вам нужно:

1. Создать аккаунт TOKEN PAY ID
2. Получить API ключи в личном кабинете
3. Использовать секретный ключ для серверных запросов

cURL
curl -X GET https://id.tokenpay.space/api/v1/users/me \
  -H "Authorization: Bearer tpid_sk_your_secret_key" \
  -H "Content-Type: application/json"

Аутентификация

TOKEN PAY ID API поддерживает два метода аутентификации:

API ключи

Используйте секретный ключ (tpid_sk_...) в заголовке Authorization:

HTTP
Authorization: Bearer tpid_sk_ваш_секретный_ключ
Важно: Никогда не используйте секретный ключ (sk) в клиентском коде. Для фронтенда используйте публичный ключ (pk) и OAuth 2.0 flow.

OAuth 2.0 Bearer Token

Для пользовательских запросов используйте access_token полученный через OAuth 2.0 flow:

HTTP
Authorization: Bearer eyJhbGciOiJSUzI1NiIs...

Лимиты запросов

API имеет следующие ограничения:

Тарифный планЗапросов/минЗапросов/день
Free6010,000
Pro300100,000
Enterprise1,000Unlimited

Заголовки ответа содержат информацию о лимитах:

Headers
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1678886400

Коды ошибок

API возвращает стандартные HTTP коды и JSON-объект ошибки:

JSON
{
  "error": {
    "code": "invalid_token",
    "message": "The access token is invalid or expired",
    "status": 401
  }
}
КодОписание
400Некорректный запрос
401Неавторизован — неверный или отсутствующий токен
403Запрещено — недостаточно прав
404Ресурс не найден
429Превышен лимит запросов
500Внутренняя ошибка сервера

OAuth 2.0 — Авторизация

TOKEN PAY ID поддерживает стандартный OAuth 2.0 Authorization Code flow для безопасной авторизации пользователей в сторонних сервисах.

Шаг 1: Redirect к авторизации

Перенаправьте пользователя на страницу авторизации:

URL
https://id.tokenpay.space/api/v1/oauth/authorize?
  client_id=tpid_pk_your_public_key&
  redirect_uri=https://yourapp.com/callback&
  response_type=code&
  scope=profile email&
  state=random_csrf_token&
  prompt=login&
  code_challenge=SHA256_HASH&
  code_challenge_method=S256
PKCE обязателен: Начиная с v2.2.0, параметры code_challenge и code_challenge_method=S256 являются обязательными для всех клиентов. Запросы без PKCE будут отклонены.
ПараметрТипОписание
client_idstringrequired — Публичный ключ
redirect_uristringrequired — URL для редиректа
response_typestringrequired — Только code
scopestringЗапрашиваемые разрешения (по умолч. profile)
statestringCSRF-токен (рекомендуется)
promptstringlogin — принудительная переавторизация, consent, none
login_hintstringEmail для предзаполнения формы входа
code_challengestringrequired — PKCE challenge (SHA-256 хеш code_verifier)
code_challenge_methodstringrequired — Только S256

Шаг 2: Обмен кода на токен

После авторизации пользователь будет перенаправлен на ваш redirect_uri с параметром code. Обменяйте его на access_token:

POST /oauth/token

POST /api/v1/oauth/token

Обмен authorization code на access token.

ПараметрТипОписание
grant_typestringrequiredauthorization_code или refresh_token
codestringrequired — Authorization code
client_idstringrequired — Ваш публичный ключ
client_secretstringСекретный ключ (обязателен для confidential-клиентов, не нужен для public + PKCE)
redirect_uristringrequired — Должен совпадать с исходным
code_verifierstringrequired — PKCE verifier (случайная строка 43–128 символов, из которой был создан code_challenge)
cURL
curl -X POST https://id.tokenpay.space/api/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "code": "abc123...",
    "client_id": "tpid_pk_...",
    "client_secret": "tpid_sk_...",
    "redirect_uri": "https://yourapp.com/callback",
    "code_verifier": "dBjftJeZ4CVP-mB92K27uhbUJU1p1r_wW1gFWFOEjXk"
  }'

Ответ

JSON — 200 OK
{
  "access_token": "eyJhbGciOiJSUzI1NiIs...",
  "token_type": "Bearer",
  "expires_in": 3600,
  "refresh_token": "tpid_rt_8a7b6c5d...",
  "scope": "profile email",
  "user": {
    "id": "tpid_usr_a1b2c3d4",
    "email": "[email protected]",
    "name": "Иван",
    "email_verified": true
  }
}

POST /oauth/revoke

POST /api/v1/oauth/revoke

Отзыв access или refresh токена.

ПараметрТипОписание
tokenstringrequired — Токен для отзыва
token_type_hintstringaccess_token или refresh_token

GET /oauth/userinfo

GET /api/v1/oauth/userinfo

Получить профиль пользователя по OAuth access token. Возвращает данные в зависимости от запрошенного scope.

cURL
curl -X GET https://tokenpay.space/api/v1/oauth/userinfo \
  -H "Authorization: Bearer ACCESS_TOKEN"
JSON — 200 OK
{
  "id": "tpid_usr_a1b2c3d4e5f6",
  "email": "[email protected]",
  "name": "Иван",
  "role": "user",
  "email_verified": true,
  "locale": "ru",
  "theme": "dark",
  "telegram_linked": true,
  "cupol_balance": 150,
  "cupol_subscription_active": true,
  "created_at": "2026-01-15T12:00:00Z"
}

POST /oauth/cancel

POST /api/v1/oauth/cancel

Уведомить enterprise о том, что пользователь закрыл окно согласия (вызывается автоматически через sendBeacon). Запускает webhook user.oauth_cancel.

ПараметрТипОписание
client_idstringrequired
reasonstringПричина: window_closed, user_cancel

POST /oauth/deny

POST /api/v1/oauth/deny

Пользователь явно отклонил запрос на авторизацию. Запускает webhook user.oauth_deny и перенаправляет с ошибкой access_denied.

ПараметрТипОписание
client_idstringrequired
redirect_uristringrequired
statestringПередаётся обратно в redirect

GET /oauth/branding

GET /api/v1/oauth/branding

Получить конфигурацию кнопок, иконки и готовый код для интеграции виджета TOKEN PAY ID. Не требует аутентификации.

JSON — 200 OK (сокращённо)
{
  "provider": "TOKEN PAY ID",
  "widget_url": "https://tokenpay.space/sdk/tpid-widget.js",
  "widget_version": "1.2.0",
  "icon": { "shield_svg": "<svg ...>" },
  "buttons": {
    "standard": { "label": "Войти через TOKEN PAY", ... },
    "icon": { "shape": "circle", ... },
    "logo": { "background": "transparent", ... }
  },
  "integration": {
    "quick_start": "<script src=... data-client-id=...>",
    "oauth_popup": "TPID.loginWithOAuth().then(...);"
  },
  "themes": ["dark", "light", "auto"],
  "languages": ["ru", "en"]
}

POST /oauth/register — Dynamic Client Registration (RFC 7591)

POST /api/v1/oauth/register

Зарегистрировать новый OAuth-клиент программно. Требуется авторизация (Bearer token или API ключ).

ПараметрТипОписание
client_namestringrequired — Название приложения
redirect_urisstring[]required — Массив разрешённых redirect URI
client_typestringpublic или confidential (по умолч. public)
client_uristringURL сайта приложения
logo_uristringURL логотипа
tos_uristringURL условий использования
policy_uristringURL политики конфиденциальности
contactsstringКонтактные email (через запятую)
scopestringЗапрашиваемые scope: openid, profile, email
JSON — 201 Created
{
  "client_id": "tpid_pk_...",
  "client_secret": "tpid_sk_...",
  "client_name": "My App",
  "redirect_uris": ["https://myapp.com/callback"],
  "client_type": "public",
  "registration_access_token": "Bearer ..."
}
Важно: client_secret показывается только один раз при регистрации. Сохраните его.

GET /oauth/client-info/:client_id

GET /api/v1/oauth/client-info/:client_id

Получить метаданные зарегистрированного OAuth-клиента. Доступно только владельцу ключа.

JSON — 200 OK
{
  "client_id": "tpid_pk_...",
  "client_name": "My App",
  "client_type": "public",
  "redirect_uris": ["https://myapp.com/callback"],
  "client_uri": "https://myapp.com",
  "logo_uri": null,
  "tos_uri": null,
  "policy_uri": null,
  "scope": "openid,profile,email"
}

Пользователи

GET /users/me

GET /api/v1/users/me

Получить профиль текущего авторизованного пользователя.

JSON — 200 OK
{
  "id": "tpid_usr_a1b2c3d4",
  "email": "[email protected]",
  "name": "Иван Чернов",
  "email_verified": true,
  "two_factor_enabled": false,
  "telegram_linked": true,
  "created_at": "2025-01-15T10:30:00Z",
  "last_login": "2026-03-13T09:45:00Z"
}

PUT /users/me

PUT /api/v1/users/me

Обновить профиль пользователя.

ПараметрТипОписание
namestringИмя пользователя
avatar_urlstringURL аватара

GET /users/activity

GET /api/v1/users/activity

История активности пользователя: входы, API вызовы, изменения безопасности.

ПараметрТипОписание
limitintegerКоличество записей (по умолчанию 50, максимум 200)
offsetintegerСмещение для пагинации
typestringФильтр: auth, api, security

GET /users/sessions

GET /api/v1/users/sessions

Список активных сессий пользователя.

JSON — 200 OK
{
  "sessions": [
    {
      "id": "ses_abc123",
      "device": "Chrome — Windows",
      "ip": "192.168.1.1",
      "location": "Saint Petersburg, RU",
      "last_active": "2026-03-13T12:00:00Z",
      "current": true
    }
  ]
}

Auth

POST /auth/send-code

POST /api/v1/auth/send-code

Отправить 6-значный код верификации на email. Используется перед регистрацией и при входе.

ПараметрТипОписание
emailstringrequired — Email адрес
typestringrequiredregister или login
Rate limit: 1 код в 60 секунд на email. Код действителен 10 минут.
JSON — 200 OK
{
  "success": true,
  "message": "Verification code sent",
  "expires_in": 600
}

POST /auth/verify

POST /api/v1/auth/verify

Верификация access токена. Используется сторонними сервисами для проверки авторизации пользователя.

ПараметрТипОписание
tokenstringrequired — Access token для проверки
JSON — 200 OK
{
  "valid": true,
  "user_id": "tpid_usr_a1b2c3d4",
  "email": "[email protected]",
  "scopes": ["profile", "email"],
  "expires_at": 1678886400
}

POST /auth/register

POST /api/v1/auth/register

Регистрация нового пользователя. Требуется предварительная отправка кода через /auth/send-code.

ПараметрТипОписание
emailstringrequired
passwordstringrequired — Минимум 8 символов
namestringrequired
email_codestringrequired — 6-значный код из email (от /auth/send-code)
Обязательно: Перед регистрацией необходимо отправить код верификации через POST /auth/send-code с type: "register".

POST /auth/login

POST /api/v1/auth/login

Двухэтапная авторизация. Первый вызов с email+password отправляет код на почту и возвращает requires_email_code: true. Второй вызов с email+password+email_code завершает авторизацию.

ПараметрТипОписание
emailstringrequired
passwordstringrequired
email_codestring6-значный код из email (обязателен на втором шаге)
two_factor_codestringTOTP код, если 2FA включена

Шаг 1 — отправка пароля:

JSON — 200 OK
{
  "requires_email_code": true,
  "requires_2fa": false,
  "message": "Verification code sent to your email"
}

Шаг 2 — подтверждение кода:

Повторите запрос, добавив email_code. При успехе возвращается access/refresh token и данные пользователя.

POST /auth/refresh

POST /api/v1/auth/refresh

Обновление access токена с помощью refresh токена.

ПараметрТипОписание
refresh_tokenstringrequired

QR-вход

Двухэтапный вход через QR-код: десктоп генерирует сессию, мобильное устройство (с активной авторизацией) подтверждает.

1. Инициализация QR-сессии

POST /api/v1/auth/qr/login-init

Создаёт QR-сессию (не требует авторизации). Возвращает sessionId и URL для QR-кода.

JSON — 200 OK
{
  "sessionId": "uuid-...",
  "ttl": 300,
  "qrUrl": "https://tokenpay.space/qr-login?sid=uuid-..."
}

2. Polling (десктоп)

GET /api/v1/auth/qr/login-poll/:sessionId

Десктоп опрашивает каждые 2 секунды. Статус: pendingapproved → возвращает токены.

3. Подтверждение (мобильное устройство)

POST /api/v1/auth/qr/login-confirm/:sessionId

Требует Authorization: Bearer. Мобильное устройство подтверждает вход.

TTL: QR-сессия живёт 5 минут. После истечения возвращается status: "expired".

API ключи

GET /keys

GET /api/v1/keys

Получить список API ключей пользователя.

POST /keys

POST /api/v1/keys

Создать новый API ключ.

ПараметрТипОписание
namestringrequired — Название ключа
scopesstring[]Массив разрешений
Важно: Секретный ключ показывается только один раз при создании. Сохраните его в безопасном месте.

DELETE /keys/:id

DEL /api/v1/keys/:key_id

Отозвать (удалить) API ключ. Все запросы с этим ключом немедленно перестанут работать.

Webhooks

Webhooks позволяют получать уведомления о событиях TOKEN PAY ID в реальном времени. Настройте URL вашего сервера в личном кабинете.

Каждый webhook запрос содержит подпись в заголовке X-TPID-Signature формата Stripe-style для верификации подлинности:

Header
X-TPID-Signature: t=1711000000,v1=hmac_sha256_hex

Для проверки подписи:

JavaScript
const crypto = require('crypto');

function verifyWebhook(body, signature, secret) {
  const parts = {};
  signature.split(',').forEach(p => {
    const [k, v] = p.split('=');
    parts[k] = v;
  });
  const expected = crypto
    .createHmac('sha256', secret)
    .update(parts.t + '.' + JSON.stringify(body))
    .digest('hex');
  return parts.v1 === expected;
}
Replay protection: Проверяйте t (timestamp) — отклоняйте запросы старше 5 минут.

Payload

JSON — Webhook Payload
{
  "event": "user.login",
  "timestamp": "2026-03-13T12:00:00Z",
  "data": {
    "user_id": "tpid_usr_a1b2c3d4",
    "ip": "192.168.1.1",
    "device": "Chrome — Windows"
  }
}

Доступные события

СобытиеОписание
user.registerНовая регистрация пользователя
user.loginУспешный вход в аккаунт
user.logoutВыход из аккаунта
user.updatedПрофиль обновлён
user.deletedАккаунт удалён
user.2fa.enabled2FA включена
user.2fa.disabled2FA отключена
key.createdСоздан новый API ключ
key.revokedAPI ключ отозван
session.createdНовая сессия
session.revokedСессия завершена
token.refreshedТокен обновлён
user.oauth_connectПользователь одобрил OAuth авторизацию
user.oauth_cancelПользователь закрыл окно OAuth
user.oauth_denyПользователь отклонил OAuth запрос

Push Notifications API

Система push-уведомлений позволяет получать уведомления в реальном времени через SSE (Server-Sent Events) или через REST API.

GET /api/v1/notifications

Получить историю уведомлений (последние 50). Требует Authorization: Bearer <token>.

Response
{
  "notifications": [
    { "id": "...", "type": "oauth_connect", "title": "New user connected", "body": "[email protected] authorized via OAuth", "is_read": false, "created_at": "2026-04-02T12:00:00Z" }
  ],
  "unread": 3
}
PUT /api/v1/notifications/:id/read

Отметить уведомление как прочитанное.

PUT /api/v1/notifications/read-all

Отметить все уведомления как прочитанные.

SSE Stream (Server-Sent Events)

GET /api/v1/notifications/stream?token=<jwt>

Подключение к потоку уведомлений в реальном времени. JWT передаётся через query-параметр (EventSource не поддерживает заголовки).

JavaScript
const es = new EventSource('/api/v1/notifications/stream?token=' + token);
es.addEventListener('notification', e => {
  const data = JSON.parse(e.data);
  console.log(data.event, data.data.title);
});
es.addEventListener('connected', e => {
  console.log('SSE connected', JSON.parse(e.data));
});
События: oauth_connect, oauth_cancelled, oauth_denied, key_created, key_revoked, user_unlink

Widget SDK v1.2 — Быстрый старт

Виджет TOKEN PAY ID предоставляет три варианта кнопок для интеграции: стандартная, круглая иконка и прозрачный логотип. Все кнопки автоматически работают с OAuth 2.0 + PKCE.

CDN: https://tokenpay.space/sdk/tpid-widget.js
Версия 1.2.0 — автообновления, без кэширования.

Минимальная интеграция (1 строка)

HTML
<script src="https://tokenpay.space/sdk/tpid-widget.js"
        data-client-id="tpid_pk_ваш_ключ"></script>

Виджет автоматически создаст кнопку «Войти через TOKEN PAY» на странице.

Три варианта кнопок

ВариантАтрибутОписание
standarddata-tpid-button="standard"Полная кнопка с иконкой щита + текст «Войти через TOKEN PAY». Подходит для основных CTA.
icondata-tpid-button="icon"Круглая кнопка с иконкой щита. Идеально для навбара рядом с Google/Apple.
logodata-tpid-button="logo"Кнопка без фона — только логотип + текст. Для минималистичного дизайна.
HTML — Все 3 варианта
<!-- Стандартная кнопка -->
<div data-tpid-button="standard"></div>

<!-- Круглая иконка -->
<div data-tpid-button="icon"></div>

<!-- Логотип без фона -->
<div data-tpid-button="logo"></div>

OAuth Popup Flow (Promise API)

Метод TPID.loginWithOAuth() открывает popup, проводит OAuth flow и возвращает Promise с authorization code.

JavaScript
TPID.loginWithOAuth({ prompt: 'login' })
  .then(function(result) {
    console.log('Auth code:', result.code);
    console.log('State:', result.state);
    // Отправьте code на ваш сервер для обмена на токен
  })
  .catch(function(err) {
    console.error('OAuth error:', err);
  });
prompt=login гарантирует, что пользователь увидит форму входа, даже если уже авторизован. Это решает проблему «залогиненного админа».

Программный API (TPID)

МетодОписание
TPID.init(opts)Инициализация с clientId, redirectUri, onSuccess, onError, lang, autoButton
TPID.open()Открыть окно авторизации (redirect flow)
TPID.loginWithOAuth(opts)OAuth popup flow → Promise<{code, state}>
TPID.renderButton(el, opts)Рендер стандартной кнопки в контейнер
TPID.renderIconButton(el, opts)Рендер круглой иконки
TPID.renderLogoButton(el, opts)Рендер прозрачной кнопки-логотипа
TPID.versionТекущая версия виджета (1.2.0)

SDK — JavaScript v2.0 (tokenpay-auth.js)

OAuth SDK с автоматической генерацией PKCE (S256). Рекомендуется как основной SDK для серверных и SPA-приложений. Для простой интеграции кнопок см. Widget SDK v1.2.

CDN: https://tokenpay.space/sdk/tokenpay-auth.js
v2.0.0 — PKCE (S256) генерируется автоматически. code_verifier сохраняется в sessionStorage.

Два типа кнопок

ТипВидОписание
icondata-mode="icon"Круглая иконка (щит TOKEN PAY) — как у Google/Apple. Размеры: 36×36 / 44×44 / 54×54 px
logodata-mode="logo"Прямоугольная кнопка с иконкой + текст «Войти через TOKEN PAY». Min/max ширина ограничена.

1. Быстрое подключение (data-атрибуты)

HTML — Кнопка LOGO (прямоугольная)
<!-- Прямоугольная кнопка с текстом -->
<script src="https://tokenpay.space/sdk/tpid-auth.js"
        data-client-id="tpid_pk_ваш_ключ"
        data-redirect-uri="https://ваш-сайт.com/callback"
        data-mode="logo"
        data-theme="dark"
        data-size="medium"
        data-lang="ru">
</script>
HTML — Кнопка ICON (круглая)
<!-- Круглая иконка -->
<script src="https://tokenpay.space/sdk/tpid-auth.js"
        data-client-id="tpid_pk_ваш_ключ"
        data-redirect-uri="https://ваш-сайт.com/callback"
        data-mode="icon"
        data-theme="light"
        data-size="large">
</script>

2. Программный API

JavaScript
// Инициализация
TokenPayAuth.init({
  clientId: 'tpid_pk_ваш_ключ',
  redirectUri: 'https://ваш-сайт.com/callback',
  theme: 'dark',
  locale: 'ru',
  onSuccess: function(data) {
    console.log('Код:', data.code);
    console.log('Verifier:', data.codeVerifier);
    // Отправьте code + codeVerifier на ваш сервер
  }
});

// Рендер кнопки в контейнер
TokenPayAuth.renderButton('#my-container', {
  mode: 'button', // 'button' | 'icon'
  theme: 'dark',   // 'dark' | 'light' | 'auto'
  size: 'medium',  // 'small' | 'medium' | 'large'
  locale: 'ru'
});

// Или запуск OAuth вручную (PKCE генерируется автоматически)
TokenPayAuth.authorize();

// Получить code_verifier для серверного обмена
const verifier = TokenPayAuth.getCodeVerifier();

3. Обмен кода на токен (серверная сторона)

cURL
curl -X POST https://tokenpay.space/api/v1/oauth/token \
  -H "Content-Type: application/json" \
  -d '{
    "grant_type": "authorization_code",
    "code": "tpid_code_...",
    "client_id": "tpid_pk_...",
    "client_secret": "tpid_sk_...",
    "redirect_uri": "https://ваш-сайт.com/callback",
    "code_verifier": "PKCE_VERIFIER"
  }'

4. Получение профиля пользователя

cURL
curl -X GET https://tokenpay.space/api/v1/oauth/userinfo \
  -H "Authorization: Bearer ACCESS_TOKEN"
JSON — 200 OK
{
  "id": "tpid_usr_a1b2c3d4e5f6",
  "email": "[email protected]",
  "name": "Иван",
  "email_verified": true,
  "created_at": "2026-01-15T12:00:00Z"
}

Параметры

Параметр / АтрибутТипОписание
clientId / data-client-idstringrequired — Публичный ключ API (tpid_pk_...)
redirectUri / data-redirect-uristringrequired — URL для редиректа после авторизации
mode / data-modestringТип кнопки: icon (круглая) или logo (прямоугольная, по умолчанию)
theme / data-themestringТема: dark (белая кнопка), light (тёмная кнопка), auto
size / data-sizestringРазмер: small (36px), medium (44px), large (54px)
lang / data-langstringЯзык: ru или en
scope / data-scopestringOAuth scope (по умолчанию openid email profile)
onSuccessfunctionCallback: ({code, state, type}) => {}
onErrorfunctionCallback при ошибке

Ограничения размеров

РежимSmallMediumLarge
icon36×36 px44×44 px54×54 px
logoh:36, w:180–320 pxh:44, w:220–400 pxh:54, w:260–480 px

SDK — Python

Install
pip install tokenpay-id
Python
from tokenpay_id import TokenPayID

client = TokenPayID(
    client_id="tpid_pk_your_public_key",
    client_secret="tpid_sk_your_secret_key"
)

# Verify a user's token
result = client.verify(access_token)
print(result.user_id)  # tpid_usr_...

# Get user profile
user = client.get_user(access_token)
print(user.email)  # [email protected]

# Webhook signature verification
is_valid = client.verify_webhook(
    payload=request.body,
    signature=request.headers["X-TPID-Signature"]
)

SDK — Go

Install
go get github.com/tokenpay/id-go
Go
package main

import (
    tpid "github.com/tokenpay/id-go"
)

func main() {
    client := tpid.NewClient(tpid.Config{
        ClientID:     "tpid_pk_your_public_key",
        ClientSecret: "tpid_sk_your_secret_key",
    })

    // Verify token
    result, err := client.Verify(accessToken)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(result.UserID) // tpid_usr_...
}

SDK — Kotlin / Android

build.gradle.kts
implementation("space.tokenpay:id-sdk:2.2.0")
Kotlin
import space.tokenpay.id.TokenPayID

val client = TokenPayID(
    clientId = "tpid_pk_your_public_key",
    clientSecret = "tpid_sk_your_secret_key",
    redirectUri = "myapp://callback"
)

// OAuth — открыть браузер
val authUrl = client.getAuthorizationUrl(
    scopes = listOf("profile", "email"),
    usePKCE = true
)
startActivity(Intent(Intent.ACTION_VIEW, Uri.parse(authUrl)))

// Обработка callback в Activity
override fun onNewIntent(intent: Intent) {
    val code = intent.data?.getQueryParameter("code") ?: return
    lifecycleScope.launch {
        val tokens = client.exchangeCode(code)
        val user = client.getUserInfo(tokens.accessToken)
        Log.d("TPID", "User: ${user.name} (${user.email})")
    }
}

// Верификация токена на сервере
val result = client.verify(accessToken)
println(result.userId) // tpid_usr_...

SDK — Swift / iOS

Package.swift / SPM
.package(url: "https://github.com/tokenpay/id-swift", from: "2.2.0")
Swift
import TokenPayID

let client = TPIDClient(
    clientId: "tpid_pk_your_public_key",
    clientSecret: "tpid_sk_your_secret_key",
    redirectURI: "myapp://callback"
)

// OAuth через ASWebAuthenticationSession
let authURL = client.authorizationURL(scopes: [.profile, .email], usePKCE: true)

let session = ASWebAuthenticationSession(
    url: authURL,
    callbackURLScheme: "myapp"
) { callbackURL, error in
    guard let code = callbackURL?.queryParam("code") else { return }
    Task {
        let tokens = try await client.exchangeCode(code)
        let user = try await client.userInfo(tokens.accessToken)
        print("User: \(user.name) — \(user.email)")
    }
}
session.start()

SDK — C# / .NET

NuGet
dotnet add package TokenPayID --version 2.2.0
C#
using TokenPayID;

var client = new TPIDClient(
    clientId: "tpid_pk_your_public_key",
    clientSecret: "tpid_sk_your_secret_key",
    redirectUri: "https://yourapp.com/callback"
);

// Генерация OAuth URL (с PKCE)
var (authUrl, verifier) = client.GetAuthorizationUrl(
    scopes: new[] { "profile", "email" },
    usePKCE: true
);

// Обмен кода на токены
var tokens = await client.ExchangeCodeAsync(code, verifier);
var user = await client.GetUserInfoAsync(tokens.AccessToken);
Console.WriteLine($"User: {user.Name} ({user.Email})");

// ASP.NET — middleware
services.AddAuthentication()
    .AddTokenPayID(options => {
        options.ClientId = "tpid_pk_...";
        options.ClientSecret = "tpid_sk_...";
    });

SDK — PHP

Composer
composer require tokenpay/id-php
PHP
use TokenPay\ID\Client;

$client = new Client([
    'client_id'     => 'tpid_pk_your_public_key',
    'client_secret' => 'tpid_sk_your_secret_key',
    'redirect_uri'  => 'https://yourapp.com/callback',
]);

// Редирект на авторизацию (с PKCE)
[$authUrl, $verifier] = $client->getAuthorizationUrl(['profile', 'email']);
$_SESSION['tpid_verifier'] = $verifier;
header("Location: $authUrl");

// Callback — обмен кода
$tokens = $client->exchangeCode($_GET['code'], $_SESSION['tpid_verifier']);
$user = $client->getUserInfo($tokens->access_token);
echo "Hello, {$user->name}!";

// Laravel — встроенный Socialite драйвер
// config/services.php
'tokenpay' => [
    'client_id' => env('TPID_CLIENT_ID'),
    'client_secret' => env('TPID_CLIENT_SECRET'),
    'redirect' => '/auth/tokenpay/callback',
]

SDK — Ruby

Gemfile
gem 'tokenpay-id', '~> 2.2'
Ruby
require 'tokenpay/id'

client = TokenPay::ID::Client.new(
  client_id: 'tpid_pk_your_public_key',
  client_secret: 'tpid_sk_your_secret_key',
  redirect_uri: 'https://yourapp.com/callback'
)

# OAuth URL
auth_url, verifier = client.authorization_url(
  scopes: ['profile', 'email'],
  pkce: true
)

# Обмен кода
tokens = client.exchange_code(params[:code], verifier)
user = client.user_info(tokens.access_token)
puts "#{user.name} (#{user.email})"

# Rails — OmniAuth стратегия
Rails.application.config.middleware.use OmniAuth::Builder do
  provider :tokenpay_id,
    ENV['TPID_CLIENT_ID'],
    ENV['TPID_CLIENT_SECRET']
end

SDK — Dart / Flutter

pubspec.yaml
dependencies:
  tokenpay_id: ^2.2.0
Dart
import 'package:tokenpay_id/tokenpay_id.dart';

final client = TPIDClient(
  clientId: 'tpid_pk_your_public_key',
  clientSecret: 'tpid_sk_your_secret_key',
  redirectUri: 'myapp://callback',
);

// Flutter — OAuth через url_launcher
final authUrl = client.getAuthorizationUrl(
  scopes: ['profile', 'email'],
  usePKCE: true,
);
await launchUrl(Uri.parse(authUrl));

// Обработка deep link
void handleCallback(Uri uri) async {
  final code = uri.queryParameters['code']!;
  final tokens = await client.exchangeCode(code);
  final user = await client.getUserInfo(tokens.accessToken);
  print('Hello, ${user.name}!');
}

SDK — Rust

Cargo.toml
[dependencies]
tokenpay-id = "2.2"
Rust
use tokenpay_id::Client;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let client = Client::new(
        "tpid_pk_your_public_key",
        "tpid_sk_your_secret_key",
    );

    // Верификация токена
    let result = client.verify(access_token).await?;
    println!("User: {}", result.user_id);

    // OAuth URL с PKCE
    let (auth_url, verifier) = client.authorization_url(
        &["profile", "email"],
        "https://yourapp.com/callback",
    )?;

    // Обмен кода
    let tokens = client.exchange_code(code, &verifier).await?;
    let user = client.user_info(&tokens.access_token).await?;
    println!("{} ({})", user.name, user.email);

    Ok(())
}

Desktop & Native Integration

Для десктопных приложений (Electron, Tauri, WPF, SwiftUI, Kotlin Desktop) используется OAuth через системный браузер с перехватом deep link.

Поддерживаемые платформы

ПлатформаМетодRedirect URI
ElectronCustom protocolmyapp://callback
TauriDeep link pluginmyapp://callback
WPF / WinUIURI activationmyapp://callback
SwiftUI / macOSCustom URL schememyapp://callback
AndroidIntent filtermyapp://callback
iOSUniversal link / schememyapp://callback
Flutteruni_links / app_linksmyapp://callback
CLI / ServerLocalhost callbackhttp://127.0.0.1:PORT/callback

Параметры для десктопных приложений

URL параметры
GET https://tokenpay.space/api/v1/oauth/authorize
  ?client_id=tpid_pk_...
  &redirect_uri=myapp://callback     // custom scheme
  &response_type=code
  &scope=profile email
  &state=RANDOM_STATE
  &code_challenge=BASE64URL(SHA256(verifier))
  &code_challenge_method=S256
  &theme=dark                         // dark | light — match app theme
  &lang=ru                            // ru | en | zh — UI language

Changelog

v2.3.0 — 13 апреля 2026

SDK

— Kotlin / Android SDK (space.tokenpay:id-sdk)
— Swift / iOS SDK (SPM)
— C# / .NET SDK (NuGet) + ASP.NET middleware
— PHP SDK (Composer) + Laravel Socialite драйвер
— Ruby SDK (Gem) + OmniAuth стратегия
— Dart / Flutter SDK (pub.dev)
— Rust SDK (crates.io)

Desktop & Native

— Документация по интеграции: Electron, Tauri, WPF, SwiftUI
— Поддержка ?theme= и ?lang= параметров для OAuth страниц
— Deep link flow с custom URL schemes
— Localhost callback для CLI-утилит

UI

— Чёрные звёзды-частицы в белой теме (инверсия тёмной)
— Частицы добавлены на все страницы экосистемы
— Обновлён favicon.ico (мультиразмерный из нового логотипа)
— Cache busting обновлён до v=11

v2.2.0 — 27 марта 2026

Безопасность

— PKCE (S256) теперь обязателен для всех OAuth-клиентов
— Ротация refresh-токенов: при обновлении выдаётся новый refresh_token
session_version — смена пароля/2FA мгновенно инвалидирует все сессии
— API-ключи запрещены из браузерных окружений (только серверный вызов)
requireScope middleware для гранулярного контроля доступа
— Webhook подписи в формате Stripe: t=timestamp,v1=hmac
— Отвязка TPID доступна только администратору
/.well-known/security.txt (RFC 9116)

Dynamic Client Registration (RFC 7591)

POST /oauth/register — программная регистрация OAuth-клиентов
GET /oauth/client-info/:id — получение метаданных клиента
PUT /oauth/register/:id — обновление метаданных клиента
— Consent screen отображает tos_uri, policy_uri, client_uri
— OpenID Discovery: registration_endpoint, client_info_endpoint

QR-вход

POST /auth/qr/login-init — создание QR-сессии
GET /auth/qr/login-poll/:id — polling статуса
POST /auth/qr/login-confirm/:id — подтверждение с мобильного
— Исправлен критический баг: QR-токены теперь корректно проходят авторизацию

API

— Строгая валидация redirect_uri (exact match)
— OpenID Discovery: pkce_required: true, code_challenge_methods_supported: ["S256"]
— API версия обновлена до 2.2.0

SDK

tokenpay-auth.js обновлён до v2.0.0
— Автоматическая генерация PKCE (S256) в authorize()
getCodeVerifier() — получение code_verifier из sessionStorage
— CSRF state validation на callback
code_verifier автоматически передаётся в exchangeCode()
— Кнопки обновлены: текст «TOKEN PAY ID», шрифт Comfortaa

v2.1.0 — 18 марта 2026

OAuth 2.0

— Поддержка prompt=login для принудительной переавторизации
— Поддержка login_hint для предзаполнения email
— Повторная валидация redirect_uri в /oauth/approve
— Новый эндпойнт: GET /oauth/branding

Widget SDK v1.2.0

— 3 варианта кнопок: standard, icon, logo
TPID.loginWithOAuth() — OAuth popup flow с Promise API
— Автоматический рендер через data-tpid-button
— Поддержка тем dark/light/auto

Нужна помощь?

Свяжитесь с нашей командой разработчиков

[email protected] Обратная связь