Перейти к основному содержанию
OAuth PKCE позволяет сторонним приложениям получать API-ключи от имени пользователей Polza.ai — без ручного создания ключей. Пользователь авторизует приложение через consent screen, выбирает организацию, scopes и лимиты расходов, после чего приложение получает готовый API-ключ.
Если вы просто хотите использовать API напрямую — создайте ключ в личном кабинете. OAuth PKCE нужен разработчикам сторонних приложений, которые запрашивают доступ у пользователей.

Как это работает

1

Генерация PKCE

Приложение генерирует пару code_verifier + code_challenge (SHA-256).
2

Перенаправление на авторизацию

Приложение перенаправляет пользователя на https://polza.ai/api/auth/authorize с параметрами.
3

Consent screen

Пользователь видит экран подтверждения — выбирает организацию, разрешённые данные и лимит расходов.
4

Callback с кодом

После подтверждения пользователь перенаправляется обратно на callback_url с параметром code.
5

Обмен кода на API-ключ

Приложение обменивает code + code_verifier на API-ключ через POST /api/auth/token.

Шаг 1: Генерация PKCE

Сгенерируйте случайный code_verifier (43-128 символов, [A-Za-z0-9\-._~]) и вычислите code_challenge как BASE64URL(SHA256(code_verifier)).
import { randomBytes, createHash } from 'crypto';

// Генерация code_verifier (43-128 символов)
const codeVerifier = randomBytes(32).toString('base64url');

// Вычисление code_challenge (S256)
const codeChallenge = createHash('sha256')
  .update(codeVerifier)
  .digest('base64url');
Сохраните code_verifier — он понадобится на шаге обмена кода. Никогда не передавайте его в URL или в открытом виде.

Шаг 2: Перенаправление на авторизацию

Перенаправьте пользователя на эндпоинт авторизации с необходимыми параметрами:
ПараметрОбязательныйОписание
response_typeдаВсегда code
callback_urlдаURL для редиректа после авторизации (HTTPS, исключение: localhost)
code_challengeдаBASE64URL(SHA256(code_verifier)), 43-128 символов
code_challenge_methodдаВсегда S256
stateнетПроизвольная строка для CSRF-защиты (возвращается без изменений)
app_nameнетНазвание приложения (отображается на consent screen)
const params = new URLSearchParams({
  response_type: 'code',
  callback_url: 'https://example.com/callback',
  code_challenge: codeChallenge,
  code_challenge_method: 'S256',
  state: 'случайная-строка-для-csrf',
  app_name: 'My App',
});

// Перенаправляем пользователя
window.location.href = `https://polza.ai/api/auth/authorize?${params}`;

Шаг 3: Обработка callback

После авторизации пользователь будет перенаправлен на ваш callback_url с параметрами:
  • При успехе: ?code=<код_авторизации>&state=<ваш_state>
  • При отказе: ?error=access_denied&state=<ваш_state>
// На вашей callback-странице
const url = new URL(window.location.href);
const code = url.searchParams.get('code');
const state = url.searchParams.get('state');
const error = url.searchParams.get('error');

if (error) {
  console.error('Пользователь отклонил авторизацию:', error);
} else if (code) {
  // Проверьте state для защиты от CSRF
  // Переходите к шагу 4 — обмен кода на ключ
}

Шаг 4: Обмен кода на API-ключ

Обменяйте код авторизации на API-ключ, отправив code_verifier для подтверждения PKCE:
const response = await fetch('https://polza.ai/api/auth/token', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    grant_type: 'authorization_code',
    code: code,
    code_verifier: codeVerifier,
    callback_url: 'https://example.com/callback',
  }),
});

const { key, user_id } = await response.json();
// key = "pza_..." — готовый API-ключ
// user_id = "usr_..." — ID пользователя
Ответ:
{
  "key": "pza_abc123...",
  "user_id": "usr_123"
}
Параметр callback_url в запросе должен точно совпадать с тем, что был указан при авторизации.

Шаг 5: Использование API-ключа

Полученный ключ работает как обычный API-ключ Polza.ai:
import OpenAI from 'openai';

const openai = new OpenAI({
  baseURL: 'https://polza.ai/api/v1',
  apiKey: key, // ключ, полученный через OAuth
});

const completion = await openai.chat.completions.create({
  model: 'openai/gpt-4o',
  messages: [{ role: 'user', content: 'Привет!' }],
});

Данные пользователя

Получите информацию о пользователе, авторизовавшем ключ, через эндпоинт GET /api/auth/userinfo:
curl -H "Authorization: Bearer pza_abc123..." \
  "https://polza.ai/api/auth/userinfo"
Ответ зависит от scopes, разрешённых пользователем:
{
  "id": "usr_123",
  "name": "Иван Иванов",
  "email": "ivan@mail.ru"
}

Доступные scopes

ScopeОписаниеОбязательный
user:idID пользователяда (всегда включён)
user:nameИмя пользователянет
user:emailEmail пользователянет
Пользователь выбирает scopes на consent screen. Scope user:id включается автоматически.

Лимиты расходов

На consent screen пользователь может установить лимит расходов для OAuth-ключа:
ПериодОписание
dayДневной лимит
weekНедельный лимит
monthМесячный лимит
totalОбщий лимит (без сброса)
Сумма указывается в рублях. При достижении лимита запросы через этот ключ будут отклоняться с ошибкой 402.

Повторная авторизация

Если пользователь повторно авторизует то же приложение для той же организации, существующий API-ключ ротируется — генерируется новый секрет, обновляются scopes и лимиты. Дубликат ключа не создаётся. Старый секрет перестаёт работать.

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

Используйте параметр state для защиты от CSRF-атак. Генерируйте случайное значение перед началом flow и проверяйте его в callback.
  • Только S256 — метод plain не поддерживается
  • HTTPS обязателен для callback_url (исключение: localhost и 127.0.0.1 для локальной разработки)
  • Код авторизации действителен 5 минут и может быть использован только один раз
  • code_verifier проверяется с защитой от timing-атак
  • Rate limit на эндпоинт /api/auth/token: 5 запросов в минуту

Ошибки

В redirect (callback_url)

ПараметрЗначениеОписание
erroraccess_deniedПользователь отклонил авторизацию

При обмене кода (POST /api/auth/token)

HTTPСообщениеПричина
400Невалидный код авторизацииКод не найден
400Код авторизации уже использованПовторная попытка обмена
400Код авторизации истёкПрошло более 5 минут
400callback_url не совпадаетURL не совпадает с указанным при авторизации
400Невалидный code_verifierPKCE-проверка не пройдена
429Too Many RequestsПревышен rate limit (5 запросов/мин)

При авторизации (GET /api/auth/authorize)

HTTPСообщениеПричина
400Невалидный callback_urlНекорректный URL или отсутствует HTTPS
400Поддерживается только метод S256Указан метод, отличный от S256
400Невалидный code_challengeНе соответствует формату Base64url (43-128 символов)

Следующие шаги

API Справочник

Полная документация эндпоинтов

Каталог моделей

Выберите модель для вашего приложения