API Reference
Полный справочник публичных эндпоинтов NexusAPI. Группировка — по способу аутентификации.
Базовый URL: https://nexusapi.dev
Способы аутентификации
NexusAPI использует три типа Bearer-токенов в зависимости от назначения:
| Тип | Заголовок | Что им покрывается |
|---|---|---|
| API-ключ | Authorization: Bearer <ключ> | Генерация задач, инфо о собственном ключе. Создаётся в panel.nexusapi.dev. |
| JWT клиента | Authorization: Bearer <jwt> | Личный кабинет: список ключей, статистика, история. Получается через /auth/login. |
| Без auth | — | Публичный каталог моделей. |
Тип Bearer-токена определяется самим эндпоинтом — API-ключ и JWT не смешиваются, нельзя «обмануть» админский ручник передав туда JWT клиента.
Генерация (API-ключ)
Основной flow: создаёшь задачу → ждёшь результат. Полное описание async-модели — на странице Задачи и статусы.
POST /generate
Создаёт новую задачу генерации. Hold стоимости на ключе происходит в той же транзакции, что и создание задачи — либо оба, либо ничего.
Заголовки: Authorization: Bearer <api_key>, Content-Type: application/json
Тело:
{ "params": { "model_name": "veo-3-fast", "prompt": "Кот играет на пианино", "duration": 8, "aspect_ratio": "16:9", "webhook_url": "https://your-app.com/callback" }}Поле params оборачивает все параметры модели. Обязательное только model_name (полный список — в каталоге); остальные зависят от модели.
Возвращает 202 Accepted:
{ "task_id": "550e8400-e29b-41d4-a716-446655440000"}Ошибки:
401— ключ не передан или невалидный402— баланса не хватает на стоимость модели403— IP не в allowlist ключа, или модель не вallowed_models404— модель неактивна422—model_nameотсутствует или цена на модель не установлена429— превышенrate_limit_per_minключа503— включён maintenance-режим
curl -X POST https://nexusapi.dev/generate \ -H "Authorization: Bearer $NEXUS_KEY" \ -H "Content-Type: application/json" \ -d '{ "params": { "model_name": "veo-3-fast", "prompt": "Кот играет на пианино", "duration": 8, "aspect_ratio": "16:9" } }'resp = requests.post( "https://nexusapi.dev/generate", headers={"Authorization": f"Bearer {KEY}"}, json={"params": { "model_name": "veo-3-fast", "prompt": "Кот играет на пианино", "duration": 8, "aspect_ratio": "16:9", }},)task_id = resp.json()["task_id"]GET /tasks/{task_id}
Возвращает текущий статус задачи и результат при completed.
Заголовки: Authorization: Bearer <api_key>
Возвращает 200:
{ "task_id": "550e8400-e29b-41d4-a716-446655440000", "status": "completed", "result": { "video_url": "https://s3.amazonaws.com/.../result.mp4", "duration": 8 }, "error": null, "created_at": "2026-05-30T12:34:56.123Z"}status — одно из pending, processing, completed, failed. См. Задачи и статусы.
Ошибки:
401— ключ не передан или невалидный403— задача принадлежит другому юзеру (этот ключ её не видит)404— задачи с таким ID нет503— maintenance-режим
GET /me/keys
Возвращает профиль клиента вместе со всеми его ключами. Используется ключ из Bearer-токена, чтобы найти клиента — отдаётся весь его набор ключей.
Возвращает 200:
{ "telegram_id": 12345, "coefficient": 1.0, "keys": [ { "id": 77, "key_value": "e6672505-1d47-...", "balance": 950.50 } ]}GET /me/balance
Возвращает только баланс ключа, переданного в Bearer.
Возвращает 200:
{ "key_balance": 950.50 }Каталог (без аутентификации)
GET /public/models
Список активных моделей с ценами в рублях. Подходит для отрисовки прайса/каталога в стороннем UI.
Без аутентификации.
Возвращает 200:
[ { "id": "veo-3-fast", "name": "Veo 3 Fast", "provider": "nexus", "kind": "video", "unit": "shot", "priceRub": 50.0 }, { "id": "kling-v2.6", "name": "Kling V2.6", "provider": "nexus", "kind": "video", "unit": "sec", "priceRub": 9.5 }]Поле unit:
"shot"— цена за одну генерацию (priceRub× 1 = hold)"sec"— цена за секунду видео (priceRub×duration= hold)
Виртуальные billing-ключи seedance (типа seedance-2.0:1080p:with_video) в этот список не попадают — отдаются только видимые модели.
Клиентская панель (JWT)
Используется фронтендом panel.nexusapi.dev и любым другим клиентом, который хочет управлять аккаунтом программно. JWT получается через /auth/login или /auth/register и живёт 7 дней.
POST /auth/register
Регистрирует нового клиента по email + паролю. На MVP-этапе email-верификации нет — JWT выдаётся сразу.
Без аутентификации.
Тело:
{ "email": "user@example.com", "password": "min8chars"}email— валидный формат, lower-cased на стороне сервераpassword— минимум 8, максимум 128 символов; bcrypt-хеш сохраняется на сервере
Возвращает 201:
{ "access_token": "eyJhbGciOiJIUzI1NiIs...", "token_type": "bearer", "user": { "telegram_id": -4050508900160186362, "email": "user@example.com", "coefficient": 1.0, "email_verified": false, "created_at": "2026-05-30T10:02:55.932251Z" }}telegram_id — синтетический отрицательный bigint (real Telegram IDs > 0), служит первичным ключом юзера во всей системе.
Ошибки:
409— email уже зарегистрирован422— невалидный email или пароль короче 8 символов
POST /auth/login
Возвращает свежий JWT для существующего юзера.
Без аутентификации.
Тело:
{ "email": "user@example.com", "password": "min8chars"}Возвращает 200: аналог /auth/register без 201. См. shape выше.
Ошибки:
401— email не существует или пароль неверный (сообщение единое, чтобы не давать перебирать существующие email)
GET /auth/me
Возвращает базовый профиль логиненого клиента (без агрегатов по балансу — для этого /customer/me/account).
Заголовки: Authorization: Bearer <jwt>
Возвращает 200:
{ "telegram_id": -4050508900160186362, "email": "user@example.com", "coefficient": 1.0, "email_verified": false, "created_at": "2026-05-30T10:02:55.932251Z"}Ошибки:
401— токен отсутствует, невалидный или просрочен
GET /customer/me/account
Профиль + агрегаты для дашборда: общий баланс по всем ключам, всего запросов, всего потрачено.
Возвращает 200:
{ "id": -4050508900160186362, "email": "user@example.com", "displayName": null, "balanceUsd": 1450.0, "totalRequests": 312, "totalSpentUsd": 8750.5, "topupBotUrl": "https://t.me/your_bot", "createdAt": "2026-05-30T10:02:55.932251Z"}GET /customer/me/keys
Все API-ключи клиента в UI-форме (с маской вместо полного секрета).
Возвращает 200:
[ { "id": 77, "name": "Key #77", "maskedKey": "e667...10b4", "monthlyLimitUsd": null, "createdAt": "2026-05-30T10:02:55.932251Z", "lastUsedAt": null, "totalRequests": 12, "totalSpentUsd": 156.0, "revoked": false }]POST /customer/me/keys
Создаёт новый API-ключ для клиента. Полный секрет возвращается ровно один раз — после сохранения восстановить нельзя, нужно создавать новый.
Тело:
{ "name": "Production server", "monthlyLimitUsd": null}name— 1-64 символа. Пока в БД не сохраняется (отображается какKey #<id>)monthlyLimitUsd— заглушка на будущее, пока не применяется
Возвращает 201:
{ "key": { "id": 78, "name": "Production server", "maskedKey": "ab12...cd34", "monthlyLimitUsd": null, "createdAt": "2026-05-30T10:02:55.932251Z", "lastUsedAt": null, "totalRequests": 0, "totalSpentUsd": 0, "revoked": false }, "secret": "ab123456-7890-abcd-ef12-3456789abcd4"}secret — полный key_value, который надо передавать в Authorization: Bearer ... при генерации. Сохрани его немедленно: панель его больше не покажет.
DELETE /customer/me/keys/{key_id}
Удаляет ключ клиента. После удаления существующие задачи продолжают выполняться (refund при провале сработает), но новые /generate дадут 401.
Возвращает 204 (без тела).
Ошибки:
403— ключ принадлежит другому юзеру404— ключа с таким ID нет
GET /customer/me/logs
История задач клиента в формате RequestLog для UI логов.
Query-параметры:
limit— 1..200, дефолт 50model— фильтр поmodel_namestatus—ok(только completed),client_errorилиserver_error(только failed)
Возвращает 200:
[ { "id": "550e8400-e29b-41d4-a716-446655440000", "createdAt": "2026-05-30T12:34:56.123Z", "endpoint": "/generate", "model": "veo-3-fast", "provider": "runblob", "inputTokens": 0, "outputTokens": 0, "costUsd": 50.0, "latencyMs": 47000, "statusCode": 200, "keyId": 77, "keyName": "Key #77" }]statusCode — синтетический: 200 для completed, 500 для failed, 202 для незавершённых.
GET /customer/me/stats
Агрегаты за последние 30 дней + разбивка по моделям. Для виджетов дашборда.
Возвращает 200:
{ "requests30d": 312, "costUsd30d": 8750.5, "requestsDelta": 0.15, "costDelta": 0.22, "successRate": 0.973, "avgLatencyMs": 0, "estimatedDaysRemaining": null, "daily": [], "byModel": [ { "model": "veo-3-fast", "provider": "nexus", "requests": 178, "costUsd": 5340.0, "share": 0.61 } ]}requestsDelta и costDelta — относительное изменение к предыдущим 30 дням (1.0 = +100%). successRate — доля completed среди всех запросов окна.
GET /customer/me/transactions
История транзакций (топ-апы, корректировки админа).
Возвращает 200:
[]Универсальные коды ответа
Применяются к большинству эндпоинтов:
| Код | Когда |
|---|---|
200 OK | GET вернул данные |
201 Created | Что-то создано (новый юзер, ключ) |
202 Accepted | Async-задача принята в обработку (/generate) |
204 No Content | DELETE прошёл |
400 Bad Request | Невалидное тело: отсутствуют обязательные параметры |
401 Unauthorized | Bearer отсутствует, неправильный или просрочен |
402 Payment Required | Баланса не хватает |
403 Forbidden | Нет прав (чужая задача / ключ, IP не в allowlist) |
404 Not Found | Ресурса нет |
409 Conflict | Email уже занят |
422 Unprocessable Entity | Pydantic не смог распарсить тело |
429 Too Many Requests | Превышен rate-limit ключа |
503 Service Unavailable | Maintenance-режим |
См. Ошибки — детали и рекомендации по обработке.
Что не вошло сюда
/admin/*— внутренние админские эндпоинты, не для публичного потребления/metrics— Prometheus метрики (для мониторинга)/docs,/redoc,/openapi.json— автоматическая OpenAPI-документация Swagger/pricing— HTML-страница публичного прайса (имеет JSON-аналог/public/models)