KADR API
Программный доступ к генерации изображений. Ключ выпускается в кабинете и встраивается в ваш проект: сервис списывает кредиты с баланса того аккаунта, которому ключ принадлежит.
Базовый адрес: https://<ваш-домен> (на время разработки — http://127.0.0.1:8777).
Оглавление
- Ключ доступа
- Кредиты и цены
- Список моделей
- Баланс
- Запуск генерации
- Состояние задания
- Ошибки
- Как правильно опрашивать
- Примеры
Ключ доступа
Выпускается на странице Кабинет → API. Показывается один раз, при выпуске: на сервере хранится не сам ключ, а его отпечаток, поэтому восстановить строку невозможно. Потеряли — выпустите новый и отзовите старый.
Вид ключа: kadr_live_ и 43 символа.
Передавать можно двумя способами, оба равнозначны:
Authorization: Bearer kadr_live_xxxxxxxx
X-API-Key: kadr_live_xxxxxxxx
Что можно делать ключом
| Действие | Ключом | Только после входа в кабинет |
|---|---|---|
| Запускать генерацию | да | |
| Смотреть состояние своих заданий | да | |
| Читать список моделей и баланс | да | |
| Пополнять баланс | да | |
| Выпускать и отзывать ключи | да | |
| Принимать условия использования | да |
Сужение намеренное: ключ живёт на чужих серверах, и его утечка не должна давать ничего, кроме траты уже оплаченных кредитов. Максимум ключей на аккаунт — 10.
Кредиты и цены
Единица тарификации — кредит, и он же одна картинка: цена не зависит от модели. Сервис работает на безлимитной лицензии поставщика, поэтому флагманский кадр обходится столько же, сколько черновой.
1 USDT = 200 кредитов, и один кредит — одна картинка любой моделью. Минимальное пополнение — 20 кредитов (0.1 USDT).
Модель (model) | Кредитов за кадр | Апскейл 2× | Референсы | Соотношения сторон | seed |
|---|---|---|---|---|---|
nbpro — Nano Banana Pro | 1 | 2 | до 10 | 16:9, 4:3, 1:1, 3:4, 9:16 | да |
nb2 — Nano Banana 2 | 1 | 2 | до 10 | те же пять | да |
nb2lite — Nano Banana 2 Lite | 1 | 2 | до 10 | те же пять | да |
gpt — GPT-Image | 1 | — | до 10 | выбора нет | нет |
flower — Flower | 1 | — | 1 (режим правки) | 16:9, 1:1, 9:16 | нет |
Апскейл 2× — единственное, что стоит дороже кадра: это вторая операция у поставщика, и она считается за две картинки.
Списание происходит в момент постановки в очередь, за все запрошенные кадры сразу. Если модель не справилась с конкретным кадром, кредиты за него возвращаются на баланс автоматически — в ответе такого кадра появится refunded_credits.
Актуальные значения всегда отдаёт GET /api/v1/models: таблица выше может отстать, ответ сервера — нет.
GET /api/v1/models
Список моделей с ценами и возможностями. Ключ не требуется.
{
"models": [
{
"id": "nbpro",
"name": "Nano Banana Pro",
"credits": 1,
"upscale": true,
"upscale_credits": 2,
"seed": true,
"aspect_ratios": ["16:9", "4:3", "1:1", "3:4", "9:16"],
"max_references": 10,
"min_references_with_edit": 0,
"about": "Лучшее качество. То, чем сделана витрина."
}
]
}
Возможности моделей различаются, и сервер это проверяет: соотношение сторон, которого у модели нет, отклоняется с кодом 400.
С seed иначе, и это важно знать заранее: модели, у которой seed не поддержан, он передаётся молча и просто ни на что не влияет. Отказа не будет. Значит и «зафиксированный» прогон на такой модели даст разные кадры, а программа об этом не узнает. Смотрите seed: true|false в ответе этого метода до отправки заявки — по нему и стройте интерфейс.
GET /api/v1/usage
Баланс аккаунта, которому принадлежит ключ.
{
"balance": 3691,
"currency": "credits",
"rate": {"credits_per_usdt": 200},
"email": "you@example.com"
}
POST /api/v1/generations
Запускает генерацию. Отвечает сразу, не дожидаясь готовности: код 202 и задание со списком кадров в состоянии queued.
Поля запроса
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
model | строка | да | идентификатор из /api/v1/models |
prompt | строка | да | описание кадра, до 1200 символов |
count | целое | нет | сколько кадров, 1–25, по умолчанию 1 |
aspect_ratio | строка | зависит | обязательно, если у модели непустой aspect_ratios |
upscale | булево | нет | увеличение 2×, удваивает цену; только там, где upscale: true |
seed | целое | нет | фиксированное зерно; к каждому кадру прибавляется его номер |
references | массив строк | нет | референсы как data:image/...;base64,... |
height | целое | нет | подгон высоты после генерации, 256–2048 |
Ответ
{
"id": "c18c58b098c8",
"status": "running",
"model": "flower",
"model_name": "Flower",
"prompt": "серый бетонный куб",
"aspect_ratio": "1:1",
"count": 2,
"charged_credits": 2,
"credits_per_image": 1,
"upscale": false,
"images": [
{"id": "67d5f8b8118f", "status": "queued", "url": null,
"error": null, "refunded_credits": null}
],
"balance": 3691
}
Про референсы
Передаются как строки data: вместе с запросом. Тело запроса ограничено 40 МБ, поэтому изображения стоит уменьшать до 1280 px по длинной стороне — качество подсказки от этого не страдает, а запрос перестаёт быть многомегабайтным.
У flower референс включает другой режим работы модели (правка изображения) и требует ровно одного файла.
GET /api/v1/generations/{id}
Состояние задания. Тело такое же, как у запуска, но с заполненными url.
Значения status у задания:
| Значение | Смысл |
|---|---|
queued | ни один кадр ещё не начат |
running | часть кадров считается |
succeeded | все кадры готовы |
failed | все кадры не удались, кредиты возвращены |
partial | часть готова, часть не удалась |
У отдельного кадра — те же значения, кроме partial.
Ссылка url абсолютная и ведёт на файл .jpg.
Кадр, сделанный по ключу API, живёт 15 минут. После этого файл удаляется с диска, ссылка отдаёт 404, и восстановить его нельзя. Скачивайте сразу, как получили succeeded, — на нашем хранилище ничего строить нельзя.
Пятнадцать минут — не оговорка и не экономия на диске. Кадры, сделанные через API, забирает программа, и она забирает их сразу; человек их руками не делал и в галерее не ждёт. Кадры, сделанные в кабинете руками, живут 3 часа — это другой срок и другой сценарий.
(До 03.09.2026 здесь было написано «Файлы хранятся у нас и не протухают». Это было неправдой уже тогда: интегратор, построивший хранилище на наших ссылках, терял всё через четверть часа.)
Ошибки
Все ошибки приходят одинаково:
{"error": {"code": "insufficient_credits",
"message": "Не хватает кредитов: нужно 20, на балансе 12"}}
code — для кода, message — для человека, по-русски.
| HTTP | code | Когда |
|---|---|---|
| 400 | bad_request | заявка не прошла проверку: нет промпта, чужое соотношение сторон, seed там, где он не поддержан |
| 400 | bad_json | тело запроса не разобралось |
| 400 | bad_count | count не целое число |
| 401 | no_key | ключ не передан |
| 401 | bad_key | ключ неизвестен или отозван |
| 402 | insufficient_credits | не хватает кредитов; списания не было |
| 403 | account_disabled | аккаунт ключа недоступен |
| 404 | not_found | задания с таким id у этого аккаунта нет |
| 413 | payload_too_large | тело больше 40 МБ |
| 422 | rejected_by_moderation | запрос отклонён правилами; кредиты не списаны |
| 429 | too_many_requests | превышен предел частоты, см. ниже; списания не было |
Отказ модерации и нехватка кредитов не стоят ничего: проверка идёт до списания.
Как правильно опрашивать
Генерация занимает от нескольких секунд до пары минут в зависимости от модели. Правильный порядок:
POST /api/v1/generations— получитьid;- опрашивать
GET /api/v1/generations/{id}раз в 3–5 секунд; - остановиться, когда
statusсталsucceeded,failedилиpartial.
Чаще раза в секунду опрашивать бессмысленно: состояние меняется реже.
Параллельные задания разрешены — сервис сам распределяет их по свободным потокам генерации и ставит в очередь то, что не поместилось. Если ёмкость занята, кадр честно подождёт в состоянии queued, а не получит отказ.
Предел частоты
120 запросов в минуту на все /api/v1/* вместе, считая опросы статуса. Сверх предела приходит 429 с телом обычного вида:
{"error": {"code": "too_many_requests",
"message": "Слишком часто. Подождите минуту."}}
Кредиты при этом не списываются. Опрос раз в 3–5 секунд на десяток одновременных заданий в предел укладывается с запасом; если у вас их сотни — опрашивайте реже, а не чаще.
Примеры
curl
curl -X POST https://ваш-домен/api/v1/generations \
-H "Authorization: Bearer kadr_live_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"model":"nbpro","prompt":"маяк в шторм, плёночное зерно","count":4,"aspect_ratio":"16:9"}'
Python
import time, requests
КЛЮЧ = "kadr_live_xxxxxxxx"
БАЗА = "https://ваш-домен"
шапка = {"Authorization": "Bearer " + КЛЮЧ}
задание = requests.post(БАЗА + "/api/v1/generations", headers=шапка, json={
"model": "nbpro",
"prompt": "маяк в шторм, плёночное зерно",
"count": 4,
"aspect_ratio": "16:9",
}).json()
if "error" in задание:
raise SystemExit(задание["error"]["message"])
пока = задание
while пока["status"] in ("queued", "running"):
time.sleep(4)
пока = requests.get(
"%s/api/v1/generations/%s" % (БАЗА, задание["id"]),
headers=шапка).json()
for кадр in пока["images"]:
if кадр["status"] == "succeeded":
имя = кадр["id"] + ".jpg"
open(имя, "wb").write(requests.get(кадр["url"]).content)
print("скачал", имя)
else:
print("не вышел кадр:", кадр["error"])
JavaScript
const КЛЮЧ = 'kadr_live_xxxxxxxx';
const БАЗА = 'https://ваш-домен';
const шапка = {
'Authorization': 'Bearer ' + КЛЮЧ,
'Content-Type': 'application/json',
};
async function сгенерировать(промпт, сколько = 1) {
const ответ = await fetch(БАЗА + '/api/v1/generations', {
method: 'POST',
headers: шапка,
body: JSON.stringify({
model: 'flower', prompt: промпт, count: сколько, aspect_ratio: '1:1',
}),
});
let задание = await ответ.json();
if (задание.error) throw new Error(задание.error.message);
while (задание.status === 'queued' || задание.status === 'running') {
await new Promise(r => setTimeout(r, 4000));
задание = await (await fetch(
`${БАЗА}/api/v1/generations/${задание.id}`, { headers: шапка }
)).json();
}
return задание.images.filter(к => к.status === 'succeeded').map(к => к.url);
}
Что API намеренно не делает
- Не отдаёт готовое изображение прямо в ответе на запуск. Генерация
небыстрая, держать соединение открытым минуту — плохой способ: рвётся связь, срабатывают таймауты прокси. Поэтому задание и опрос.
- Не присылает уведомление о готовности. Веб-хуков пока нет; если они
понадобятся, скажите — это следующий разумный шаг.
- Не даёт удалять и перегенерировать кадры. Это операции кабинета: они
меняют историю аккаунта, и делать их из встроенного ключа опаснее, чем полезнее.