ИИ в вашем приложении за счёт пользователя
Добавьте кнопку «Войти через Polza». Пользователь подтверждает доступ, приложение получает его API-ключ и отправляет запросы к 400+ моделям. Polza.ai списывает деньги с баланса пользователя, и ваш счёт за API не растёт вместе с аудиторией.
- Лимит расходов ставит пользователь
- Один ключ на 400+ моделей
- OpenAI-совместимый API
- Callback на localhost для разработки
Запрос доступа
Организация
Доступ к данным
- User IDВсегда передаётся
- ИмяПередать ваше имя приложению
- EmailПередать ваш email приложению
Установить лимит расходов
Сумма (₽)
Период
Приложение получит API-ключ для организации Личная и сможет выполнять запросы к API от вашего имени.
Что такое вход через Polza
Обычно приложение с нейросетью ходит в API со своим ключом. Каждый запрос пользователя оплачивает автор. Тысяча пользователей — тысяча чужих диалогов на вашем счёте.
Со входом через Polza у каждого пользователя свой API-ключ. Polza.ai выпускает его после согласия пользователя и привязывает к балансу организации, которую он выбрал. Приложение хранит ключ и отправляет с ним запросы, как с обычным ключом Polza.ai.
Технически это OAuth 2.0 с PKCE: обмен кода на ключ защищён одноразовым секретом, который знает только ваше приложение.
Для каких проектов
Подходит везде, где запросы к модели делает пользователь и их число заранее неизвестно.
Telegram-бот с нейросетью
Бот отвечает, пересказывает, рисует. Каждый новый подписчик добавляет запросы, и при своём ключе их оплачиваете вы.
Подписчик входит через аккаунт Polza.ai и платит за свои запросы сам.
ИИ-чат или ассистент на сайте
Виджет на сайте, который отвечает посетителям или помогает с текстом. Нагрузку сложно предсказать, особенно после публикации в соцсетях.
Расход ограничен лимитом и балансом каждого пользователя.
Приложение на Lovable, Cursor или Replit
Вайбкодинг-проект, который вы показали друзьям или выложили в открытый доступ. Платить за всех, кто его попробует, накладно.
Агент добавит вход по промпту из этой страницы.
Десктопное приложение и CLI
Программа на компьютере пользователя, которой нужен доступ к моделям. Просить вставить ключ вручную неудобно.
Callback принимает localhost и 127.0.0.1.
Плагин, расширение, open source
Код открыт, зашить в него свой ключ нельзя. Пользователю приходится заводить ключ и копировать его в настройки.
Вход заменяет ручную вставку ключа.
Сервис для команды
Внутренний инструмент, которым пользуются сотрудники разных отделов. Расходы нужно разнести по подразделениям.
Пользователь выбирает организацию, с баланса которой платить.
Свой ключ или вход через Polza
| Свой ключ в коде приложения | Вход через Polza | |
|---|---|---|
| Кто платит за запросы | Вы, за всех пользователей | Каждый пользователь со своего баланса |
| Рост аудитории | Счёт за API растёт вместе с ней | Ваш счёт за API не меняется |
| Лимит расходов | Ставите сами, общий на всех | Пользователь ставит свой: на день, неделю, месяц или разовый |
| Если ключ утёк | Под угрозой весь ваш баланс | Затронут один пользователь: ключ ограничен его лимитом и балансом |
| Что хранит приложение | Один ключ на сервере | Ключ каждого пользователя |
| Доступ к моделям | 400+ моделей по одному ключу | 400+ моделей по ключу пользователя |
Как подключить нейросеть к сайту, боту или приложению
Ниже — подключение входа через Polza по OAuth PKCE: пять шагов и готовый код под три типа проектов. После входа приложение получает API-ключ пользователя и отправляет запросы к GPT, Claude, DeepSeek, Gemini и другим моделям из каталога. Регистрировать приложение в Polza.ai заранее не нужно: в запросе авторизации нет client_id, приложение называет себя параметром app_name.
Что понадобится
Адрес для callback
Страница или эндпоинт на HTTPS, куда Polza.ai вернёт пользователя. Для разработки подойдут localhost и 127.0.0.1 без HTTPS.
Место для ключей
База или сессия на сервере. Ключ каждого пользователя хранится у вас и не уходит в браузер.
OpenAI SDK
Любой OpenAI-совместимый клиент: openai для Node.js и Python, LangChain, Vercel AI SDK. Адрес API — https://polza.ai/api/v1.
Пять шагов OAuth PKCE
Шаг 1
Сгенерируйте пару PKCE
Случайная строка
code_verifierдлиной 43–128 символов и её SHA-256 хешcode_challengeв Base64url. Verifier сохраните у себя, в URL его не передают.TypeScript · шаг 1import { randomBytes, createHash } from 'crypto'; const codeVerifier = randomBytes(32).toString('base64url'); const codeChallenge = createHash('sha256') .update(codeVerifier).digest('base64url');Шаг 2
Отправьте пользователя на экран согласия
Перенаправьте на
https://polza.ai/api/auth/authorize. Название изapp_nameпользователь увидит на экране.state— до 256 символов.TypeScript · шаг 2const params = new URLSearchParams({ response_type: 'code', callback_url: 'https://mybot.ru/callback', code_challenge: codeChallenge, code_challenge_method: 'S256', state: csrfToken, app_name: 'Мой бот', }); location.href = `https://polza.ai/api/auth/authorize?${params}`;Шаг 3
Примите callback
После согласия Polza.ai вернёт пользователя на ваш
callback_urlс параметрамиcodeиstate. Если он отказался, придётerror=access_denied.TypeScript · шаг 3// страница https://mybot.ru/callback const url = new URL(location.href); const code = url.searchParams.get('code'); const state = url.searchParams.get('state'); const error = url.searchParams.get('error'); if (state !== csrfToken) throw new Error('CSRF'); if (error === 'access_denied') showLoginAgain(); // иначе — шаг 4, обмен code на ключШаг 4
Обменяйте код на ключ
POST на
/api/auth/tokenс кодом и verifier. Код живёт 5 минут и срабатывает один раз.TypeScript · шаг 4const res = await fetch('https://polza.ai/api/auth/token', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ grant_type: 'authorization_code', code, code_verifier: codeVerifier, callback_url: 'https://mybot.ru/callback', }), }); if (!res.ok) throw new Error('Обмен кода не удался'); const { key, user_id } = await res.json(); // key = "pza_…", user_id = "usr_…"Шаг 5
Отправляйте запросы с ключом пользователя
Ключ работает как обычный API-ключ Polza.ai. Подойдёт любой OpenAI SDK, меняется только адрес API.
TypeScript · шаг 5import OpenAI from 'openai'; const ai = new OpenAI({ baseURL: 'https://polza.ai/api/v1', apiKey: key, // ключ этого пользователя }); await ai.chat.completions.create({ model: 'openai/gpt-5.4-mini', messages: [{ role: 'user', content: 'Привет!' }], });
Те же шаги на Python и cURL — в документации.
Где хранить ключ и куда вести callback
| Проект | Где хранить ключ | callback_url |
|---|---|---|
| Сайт с ИИ-чатом | Сессия или таблица пользователей на сервере | https://ваш-сайт/auth/polza/callback |
| Telegram-бот | База, ключ по Telegram ID пользователя | https://ваш-сервер/callback |
| Приложение на Lovable, Cursor, Replit | Серверная часть проекта | https://ваш-домен/auth/polza/callback |
| Десктоп и CLI | Файл настроек или хранилище ключей ОС на компьютере пользователя | http://localhost:порт/callback |
Как добавить ИИ-чат на сайт
Кнопка «Войти через Polza» ведёт на ваш сервер, сервер отправляет человека на экран согласия и принимает код. Ключ сохраняется в сессии. Виджет чата шлёт сообщения на ваш эндпоинт, а эндпоинт ходит в модель с ключом этого посетителя.
Пример на Node.js и Express — три маршрута. Если не хватает лимита расходов или баланса, Polza.ai вернёт 402, и сайт покажет человеку понятное сообщение. Нужны пакеты express, express-session и openai.
import express from 'express';
import session from 'express-session';
import { randomBytes, createHash } from 'crypto';
import OpenAI from 'openai';
const app = express();
app.use(express.json());
// в проде — хранилище сессий в базе, не в памяти
app.use(session({ secret: process.env.SESSION_SECRET, resave: false, saveUninitialized: false }));
const CALLBACK = 'https://mysite.ru/auth/polza/callback';
// 1–2. Кнопка «Войти через Polza» ведёт сюда
app.get('/auth/polza', (req, res) => {
const verifier = randomBytes(32).toString('base64url');
const challenge = createHash('sha256').update(verifier).digest('base64url');
const state = randomBytes(16).toString('hex');
req.session.pkce = { verifier, state };
const params = new URLSearchParams({
response_type: 'code', callback_url: CALLBACK,
code_challenge: challenge, code_challenge_method: 'S256',
state, app_name: 'Мой сайт',
});
res.redirect(`https://polza.ai/api/auth/authorize?${params}`);
});
// 3–4. Polza возвращает пользователя с кодом, меняем код на ключ
app.get('/auth/polza/callback', async (req, res) => {
const { code, state, error } = req.query;
if (error || state !== req.session.pkce?.state) return res.redirect('/');
const r = await fetch('https://polza.ai/api/auth/token', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
grant_type: 'authorization_code', code,
code_verifier: req.session.pkce.verifier, callback_url: CALLBACK,
}),
});
if (!r.ok) return res.redirect('/');
const { key } = await r.json();
req.session.polzaKey = key; // ключ остаётся на сервере
res.redirect('/chat');
});
// 5. Чат на сайте шлёт сообщения сюда, сервер идёт в модель с ключом пользователя
app.post('/api/chat', async (req, res) => {
if (!req.session.polzaKey) return res.status(401).end();
const ai = new OpenAI({ baseURL: 'https://polza.ai/api/v1', apiKey: req.session.polzaKey });
try {
const r = await ai.chat.completions.create({ model: 'openai/gpt-5.4-mini', messages: req.body.messages });
res.json(r.choices[0].message);
} catch (e) {
if (e.status === 402) return res.status(402).json({ error: 'Не хватает лимита расходов или баланса' });
res.status(500).json({ error: 'Модель не ответила' });
}
});
app.listen(3000);Как добавить нейросеть в Telegram-бота
Бот присылает ссылку на вход в ответ на /start. В параметре state бот запоминает, какому пользователю Telegram принадлежит вход. Callback принимает тот же процесс через FastAPI, меняет код на ключ и сохраняет его по Telegram ID. После этого каждое сообщение пользователя уходит в модель с его ключом.
Пример на Python: aiogram 3, FastAPI и openai в одном файле. Callback должен быть доступен из интернета по HTTPS. Пакеты: aiogram, fastapi, uvicorn, httpx, openai.
# aiogram 3 + FastAPI в одном процессе
import asyncio, base64, hashlib, os, secrets
from urllib.parse import urlencode
import httpx, uvicorn
from aiogram import Bot, Dispatcher, F
from aiogram.filters import CommandStart
from aiogram.types import Message
from fastapi import FastAPI
from fastapi.responses import PlainTextResponse
from openai import AsyncOpenAI, APIStatusError
CALLBACK = "https://mybot.ru/callback"
bot, dp, api = Bot(os.environ["BOT_TOKEN"]), Dispatcher(), FastAPI()
pending, keys = {}, {} # в проде — база данных
@dp.message(CommandStart())
async def start(m: Message):
verifier = secrets.token_urlsafe(32)
digest = hashlib.sha256(verifier.encode()).digest()
challenge = base64.urlsafe_b64encode(digest).rstrip(b"=").decode()
state = secrets.token_urlsafe(16)
pending[state] = (m.from_user.id, verifier)
url = "https://polza.ai/api/auth/authorize?" + urlencode({
"response_type": "code", "callback_url": CALLBACK,
"code_challenge": challenge, "code_challenge_method": "S256",
"state": state, "app_name": "Мой бот",
})
await m.answer(f"Войдите через Polza, и бот будет отвечать за счёт вашего баланса:\n{url}")
@api.get("/callback", response_class=PlainTextResponse)
async def callback(code: str = "", state: str = "", error: str = ""):
user_id, verifier = pending.pop(state, (None, None))
if error or user_id is None:
return "Вход отменён"
async with httpx.AsyncClient() as c:
r = await c.post("https://polza.ai/api/auth/token", json={
"grant_type": "authorization_code", "code": code,
"code_verifier": verifier, "callback_url": CALLBACK,
})
if not r.is_success:
return "Вход не удался, нажмите /start ещё раз"
keys[user_id] = r.json()["key"]
await bot.send_message(user_id, "Готово. Задайте вопрос.")
return "Готово, вернитесь в Telegram"
@dp.message(F.text)
async def ask(m: Message):
key = keys.get(m.from_user.id)
if not key:
return await m.answer("Сначала нажмите /start")
ai = AsyncOpenAI(base_url="https://polza.ai/api/v1", api_key=key)
try:
r = await ai.chat.completions.create(
model="openai/gpt-5.4-mini",
messages=[{"role": "user", "content": m.text}],
)
await m.answer(r.choices[0].message.content)
except APIStatusError as e:
await m.answer("Не хватает лимита расходов или баланса" if e.status_code == 402 else "Модель не ответила")
async def main():
server = uvicorn.Server(uvicorn.Config(api, host="0.0.0.0", port=8000))
await asyncio.gather(server.serve(), dp.start_polling(bot))
asyncio.run(main())Как подключить нейросеть к приложению на Lovable или Cursor
Если код пишет агент, отдайте ему промпт из раздела ниже. Агент прочитает .md-версию документации и соберёт те же маршруты, что в примере для сайта. Проверьте за ним два места: ключ хранится на сервере, а state сверяется в callback.
Вход в десктопном приложении и CLI
Программа поднимает локальный сервер на свободном порту, открывает ссылку на вход в браузере и ждёт один запрос с кодом. HTTPS для localhost и 127.0.0.1 не нужен. Ключ после обмена сохраните на компьютере пользователя.
import http.server, urllib.parse, webbrowser
# authorize_url собран как в шаге 2, с callback_url=http://localhost:8765/callback
class Callback(http.server.BaseHTTPRequestHandler):
def do_GET(self):
u = urllib.parse.urlparse(self.path)
if u.path != "/callback": # favicon и прочие запросы браузера
self.send_response(404)
self.end_headers()
return
q = urllib.parse.parse_qs(u.query)
self.server.code = q.get("code", [None])[0]
self.server.state = q.get("state", [None])[0]
self.server.done = True
self.send_response(200)
self.end_headers()
done = "Вход выполнен" if self.server.code else "Вход отменён"
self.wfile.write(f"{done}, вкладку можно закрыть".encode())
srv = http.server.HTTPServer(("127.0.0.1", 8765), Callback)
webbrowser.open(authorize_url)
srv.done = False
while not srv.done: # ждём запрос на /callback
srv.handle_request()
if srv.state != state: # state из шага 2
raise SystemExit("state не совпал, вход прерван")
if srv.code is None:
raise SystemExit("Пользователь отклонил доступ")
# обменяйте srv.code на ключ, как в шаге 4Код целиком — в документации
Примеры на TypeScript, Python и cURL, параметры запросов и ответы сервера.
Что видит пользователь
Экран согласия открывается на polza.ai. Пользователь видит название приложения из app_name и домен из callback_url. Приложение, которое Polza.ai не проверяла, помечено «Не верифицировано». Дальше пользователь решает три вещи.
С какого баланса платить
Если у пользователя несколько организаций, он выбирает одну. Polza.ai выпускает ключ в ней, и запросы списываются с её баланса.
Какие данные передать
ID передаётся всегда. Имя на экране уже отмечено, email — нет; пользователь может снять или поставить любую из двух отметок. Отмеченное вы получите через GET /api/auth/userinfo.
Сколько можно потратить
Лимит в рублях на день, неделю, месяц или разовый, без сброса. По умолчанию экран предлагает 100 ₽ в день; лимит можно поменять или снять. Когда лимит кончится, запросы с ключом вернут ошибку 402.
Путь пользователя
- 1
Нажимает «Войти через Polza»
Кнопка в вашем приложении, рядом с обычным входом.
- 2
Входит в аккаунт на polza.ai
Без аккаунта Polza.ai сначала откроет вход и регистрацию, затем вернёт человека к запросу доступа.
- 3
Подтверждает доступ
Выбирает организацию, данные и лимит расходов на экране согласия.
- 4
Возвращается в приложение
Ваш callback получает код, сервер обменивает его на ключ.
- 5
Пользуется
Запросы списываются с баланса его организации в Polza.ai. Когда лимит или баланс кончится, приложение получит 402.
Данные пользователя
| Scope | Что вы получите | Обязательный |
|---|---|---|
user:id | ID пользователя вида usr_123 | Да, включён всегда |
user:name | Имя | Нет, отмечено по умолчанию, пользователь может снять |
user:email | Нет, не отмечено по умолчанию, пользователь может поставить |
Лимиты расходов
| Период | Как работает |
|---|---|
day | Лимит на день |
week | Лимит на неделю |
month | Лимит на месяц |
total | Разовый лимит, без сброса |
Что получаете вы
API-ключ пользователя
Строка вида pza_…. Работает с https://polza.ai/api/v1 и любым OpenAI-совместимым SDK.
ID и профиль
user_id приходит вместе с ключом. Имя и email — по GET /api/auth/userinfo, если пользователь их разрешил.
Весь каталог моделей
Ключ открывает те же 400+ моделей, что и обычный: текст, код, изображения, видео, речь.
Повторный вход без дублей
Если пользователь снова авторизует приложение в той же организации, ключ ротируется: новый секрет, новые scopes и лимиты. Старый секрет перестаёт работать.
Понятный сигнал о деньгах
Ответ 402 значит, что у пользователя кончился лимит расходов или баланс. Покажите ему ссылку на пополнение или предложите поднять лимит.
Ноль на вашем счёте
Запросы оплачивает пользователь. Подключение входа в Polza.ai бесплатное, комиссии с разработчика нет.
Промпт для Cursor, Lovable и Claude Code
Если приложение пишет агент, код вручную не нужен. Скопируйте промпт и подставьте свой домен и название.
Агент прочитает .md-версию документации по ссылке. В ней те же шаги, что на этой странице, без вёрстки.
- Cursor
- Lovable
- Claude Code
- Replit
- Bolt
- Codex
Как подключить сам Claude Code к Polza — на странице Claude Code.
Добавь в приложение вход через Polza.ai по OAuth PKCE.
Документация: https://polza.ai/docs/gaidy/oauth-pkce.md
1. Кнопка «Войти через Polza» на странице входа.
2. callback_url: https://<мой-домен>/auth/polza/callback
(для локальной разработки — http://localhost:<порт>/...)
3. app_name: <название приложения>
4. Полученный ключ pza_… сохрани у пользователя на сервере,
в браузер его не отдавай.
5. Все запросы к модели отправляй через OpenAI SDK
с baseURL https://polza.ai/api/v1 и ключом пользователя.
6. На ответ 402 покажи: «Не хватает лимита расходов или баланса».Безопасность
Эти правила Polza.ai проверяет на своей стороне.
Только S256
Метод plain не поддерживается: challenge всегда SHA-256 от verifier.
HTTPS для callback
Адрес возврата должен быть на HTTPS. Исключение — localhost и 127.0.0.1 для разработки.
Код живёт 5 минут
Код авторизации одноразовый. Повторный обмен вернёт ошибку.
5 обменов в минуту
На /api/auth/token — не больше 5 обменов в минуту с одного IP-адреса. Шестой запрос за минуту получит 429.
Проверка verifier
Сервер сверяет code_verifier с защитой от timing-атак.
Параметр state
Генерируйте случайный state перед входом и сверяйте его в callback. Так вы закроете CSRF.
Если вход не работает
Ошибки, которые возвращают authorize, token и запросы с ключом.
Пользователь отклонил доступ
На callback придёт error=access_denied. Покажите кнопку входа ещё раз, ключа в этом случае нет.
400: невалидный код или код уже использован
Код одноразовый и живёт 5 минут. Начните вход заново. Частая причина — повторная отправка формы или перезагрузка callback-страницы.
400: callback_url не совпадает
callback_url при обмене должен буквально совпадать с тем, что был в ссылке авторизации, включая слеш на конце.
400: невалидный code_verifier
Verifier не соответствует challenge. Проверьте, что сохраняете verifier между шагами 1 и 4 для того же пользователя.
400 на authorize: невалидный callback_url или code_challenge
Callback должен быть на HTTPS или localhost. Challenge — Base64url длиной 43–128 символов, без знаков = на конце.
402 при запросе к модели
Пользователь исчерпал лимит, который поставил на экране согласия, или на балансе организации не хватает денег. Лимит он поднимет в кабинете или повторным входом, баланс пополнит в кабинете.
429 при обмене кода
Больше 5 обменов в минуту с одного IP-адреса. Обычно это цикл повторов в коде callback. Код живёт 5 минут — обмен можно повторить через минуту.
Нужны все коды ответов?
Таблицы ошибок authorize и token — в документации.
Вопросы и ответы
Сколько платит разработчик?
Нисколько. Подключение входа через Polza бесплатное, комиссии с разработчика Polza.ai не берёт. Запросы оплачивает пользователь со своего баланса.
Получает ли разработчик долю от расходов пользователей?
Сейчас нет. Партнёрскую программу для приложений со входом через Polza.ai планируем, но условий и сроков пока нет.
Что если у пользователя нет аккаунта Polza.ai?
Экран согласия сначала откроет вход и регистрацию Polza.ai, после входа человек вернётся к запросу доступа. Пополнить баланс прямо с экрана согласия нельзя: это делается в кабинете, а пока баланс пуст, запросы с ключом возвращают 402.
Как пользователь отзывает доступ?
В кабинете Polza.ai, в разделе «API-ключи»: ключ приложения помечен OAuth и называется «OAuth: <название приложения>». Там пользователь меняет лимит расходов, деактивирует или удаляет ключ, после чего запросы с ним перестают проходить.
Нужно ли регистрировать приложение?
Нет. В запросе авторизации нет client_id: приложение передаёт название в параметре app_name, и пользователь видит его на экране согласия вместе с доменом callback_url. Пока Polza.ai не проверила приложение, рядом с названием стоит отметка «Не верифицировано».
Работает ли вход в десктопном приложении или CLI?
Да. Polza.ai принимает callback на localhost или 127.0.0.1 без HTTPS: приложение поднимает локальный сервер и принимает код.
Какие модели доступны по ключу пользователя?
Те же, что по обычному ключу Polza.ai: весь каталог из 400+ моделей. Модель вы выбираете в запросе.
Что будет, если пользователь войдёт второй раз?
Polza.ai ротирует ключ в той же организации: генерирует новый секрет, обновляет scopes и лимиты. Сохраните новый ключ, старый перестанет работать.
Добавьте вход через Polza
Пять шагов в коде или один промпт для агента. Пользователи сами оплачивают свои запросы в Polza.ai, со своего баланса.
Остались вопросы? Документация по OAuth PKCE, поддержка в Telegram или support@polza.ai
Страницу проверила редакция Polza.AI, обновлено . Модели и цены — в каталоге.