Generations API
Создание генераций, опрос статуса, список задач и загрузка референсов для image-to-image
Generations API — основной эндпоинт IskraGen. Одна и та же схема запроса работает для всех моделей: картинки, видео, озвучка, музыка. Тип медиа и набор параметров определяются выбранной моделью.
Все запросы авторизуются API-ключом (см. Authentication):
Authorization: Bearer isk_live_<prefix>_<secret>
Базовый URL:
https://api.iskragen.ru/v1. Канонический публичный путь —/v1/*. Внутри приложения те же роуты смонтированы под/api/v1/*— это внутренняя деталь, в интеграциях используйте/v1/*.
Модель асинхронная
Генерация — асинхронная операция. POST /v1/generations не ждёт готового медиа: он ставит задачу в очередь, сразу списывает стоимость (hold) и возвращает HTTP 202 с id и статусом PENDING. Готовый результат вы получаете одним из двух способов:
- Polling — опрашивайте
GET /v1/generations/:id, покаstatusостаётсяPENDINGилиPROCESSING; все возможные значения перечислены ниже. - Webhooks — для длинных задач (видео, музыка) подпишитесь на
generation.completed/generation.failedи не опрашивайте вручную.
Основной жизненный цикл статуса:
PENDING → PROCESSING → SUCCEEDED
↘ FAILED (средства возвращаются на баланс автоматически)
| Статус | Значение |
|---|---|
PENDING | Задача принята и стоит в очереди. |
PROCESSING | Провайдер выполняет генерацию. |
SUCCEEDED | Готово. Результат в outputUrls. |
FAILED | Окончательная ошибка (после всех retry). Списанные средства возвращены. |
ENQUEUE_FAILED | Не удалось зарезервировать средства или передать задачу на обработку; обработка не началась. |
REFUNDED | — |
CANCELLED | — |
POST /v1/generations
Создать генерацию.
Тело запроса
| Поле | Тип | Обяз. | Описание |
|---|---|---|---|
modelSlug | string | да | Публичный slug модели IskraGen (например gpt-image-2-text-to-image). Источник правды — каталог (раздел «Discovery» ниже) и «ID модели» в карточке модели. |
prompt | string | да | От 1 символа. Верхняя граница зависит от модели: по умолчанию 4000 символов, у отдельных моделей меньше или больше. Актуальное значение — поле promptMaxChars модели в GET /v1/catalog; абсолютный максимум запроса — 10 000 символов. Превышение лимита модели возвращает VALIDATION_ERROR (400) с details.reason: "PROMPT_TOO_LONG", details.limit и details.actual; деньги не списываются. |
negativePrompt | string | нет | До 2000 символов. |
params | object | нет | Параметры, специфичные для модели (например aspect_ratio, resolution, duration, input_urls). Мёрджатся поверх defaultParams модели. См. раздел «aspect_ratio vs width/height» ниже. |
width | integer | нет | 256–4096. Только для части прежних пиксельных моделей. Для актуального каталога используйте params.aspect_ratio + params.resolution. |
height | integer | нет | 256–4096. См. width. |
durationSec | integer | нет | 1–600. Длительность для видео/аудио, если модель принимает секунды. |
seed | integer | нет | ≥ 0. Для воспроизводимости. |
idempotencyKey | string | нет | 1–64 символа. Повторный запрос с тем же ключом вернёт ту же генерацию, а не создаст новую. Предпочтительный способ — заголовок Idempotency-Key (см. ниже). |
Заголовки
| Заголовок | Обяз. | Описание |
|---|---|---|
Idempotency-Key | нет | 1–64 символа. Повторный запрос с тем же ключом вернёт ту же генерацию. Если заголовок не передан, используется поле idempotencyKey из тела запроса; если переданы оба и значения различаются — приоритет у заголовка. Значение длиннее 64 символов или пустое → 400. |
Тело запроса при повторе ключа не сравнивается. В пределах одного пользователя тот же idempotencyKey возвращает существующую генерацию (id, status, costRub), не создаёт новую и не списывает деньги второй раз, даже если остальные поля запроса отличаются.
curl -X POST https://api.iskragen.ru/v1/generations \
-H "Authorization: Bearer $ISKRAGEN_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-42-retry-1" \
-d '{ "modelSlug": "gpt-image-2-text-to-image", "prompt": "Кот-космонавт" }'
Ответ 202 Accepted
{
"id": "0192f0c4-8a1e-7b3d-9f21-2c5e6a4b7d90",
"status": "PENDING",
"costRub": 7
}
costRub— стоимость, уже зарезервированная (hold) с баланса в момент запроса. ПриFAILEDвозвращается автоматически.id— UUIDv7, передавайте его вGET /v1/generations/:id.
Пример
curl -X POST https://api.iskragen.ru/v1/generations \
-H "Authorization: Bearer $ISKRAGEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"modelSlug": "gpt-image-2-text-to-image",
"prompt": "Кот-космонавт на фоне Сатурна, фотореализм",
"params": { "aspect_ratio": "1:1", "resolution": "1K" }
}'
GET /v1/generations/:id
Получить генерацию по id. Используется для polling'а.
Ответ 200 OK
{
"id": "0192f0c4-8a1e-7b3d-9f21-2c5e6a4b7d90",
"userId": "0192...",
"modelId": "legacy-model-id",
"modelSlug": "gpt-image-2-text-to-image",
"modelName": "GPT Image 2",
"mediaType": "IMAGE",
"prompt": "Кот-космонавт на фоне Сатурна, фотореализм",
"params": { "aspect_ratio": "1:1", "resolution": "1K" },
"status": "SUCCEEDED",
"outputUrls": ["https://s3.twcstorage.ru/.../result.webp"],
"costRub": 7,
"mediaPriceRub": 6,
"chargeStatus": null,
"errorMessage": null,
"errorCode": null,
"startedAt": "2026-07-01T12:00:40.000Z",
"finishedAt": "2026-07-01T12:00:42.000Z",
"createdAt": "2026-07-01T12:00:39.000Z"
}
| Поле | Тип | Описание |
|---|---|---|
modelSlug | string | Публичный идентификатор модели. |
modelId | string | Устарело. Внутренний идентификатор; используйте modelSlug. |
status | string | PENDING | PROCESSING | SUCCEEDED | FAILED | REFUNDED | CANCELLED | ENQUEUE_FAILED. |
outputUrls | string[] | Ссылки на результат (S3). Пусто, пока status ≠ SUCCEEDED. |
errorCode / errorMessage | string | null | Заполняются при FAILED. |
mediaPriceRub | number | null | Реальная цена медиа (когда доступна). |
chargeStatus | string | null | Технический статус биллингового контура. null — контур для вашего аккаунта не задействован (текущий режим по умолчанию): списание и возврат уже произошли, но отдельного статуса для них нет — ориентируйтесь на status и баланс. Если контур включён, возможные значения — PENDING / CHARGED / RELEASED / FAILED / FAILED_EXPIRED. |
startedAt / finishedAt | string | null | ISO-8601 UTC. |
Пример polling'а (Node.js)
async function waitForResult(id) {
for (;;) {
const res = await fetch(`https://api.iskragen.ru/v1/generations/${id}`, {
headers: { Authorization: `Bearer ${process.env.ISKRAGEN_API_KEY}` },
});
const gen = await res.json();
if (gen.status === "SUCCEEDED") return gen.outputUrls;
if (gen.status !== "PENDING" && gen.status !== "PROCESSING") {
throw new Error(`${gen.status}: ${gen.errorCode}: ${gen.errorMessage}`);
}
await new Promise((r) => setTimeout(r, 2000)); // 2 сек между опросами
}
}
GET /v1/generations/:id/download
Скачать файл результата по индексу. Авторизация — API-ключ или сессия.
Query-параметры
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
index | integer | 0 | Номер файла результата, от 0 до 15. |
API сам отдаёт байты файла, а не редирект или ссылку. Ответ содержит Content-Type, Content-Disposition: attachment; filename="…", Cache-Control: private, no-store и, если размер известен, Content-Length.
curl -L -o result.png \
-H "Authorization: Bearer $KEY" \
https://api.iskragen.ru/v1/generations/<id>/download
Ошибки:
| HTTP | code | Когда |
|---|---|---|
| 404 | NOT_FOUND | Генерации нет, она принадлежит другому пользователю или у неё нет файла с таким index. |
| 502 | OUTPUT_FETCH_FAILED | Файл не удалось получить из хранилища. |
GET /v1/generations
Список генераций пользователя, cursor-пагинация (новые первыми).
Query-параметры
| Параметр | Тип | По умолчанию | Описание |
|---|---|---|---|
limit | integer | 20 | 1–100. |
cursor | string | — | createdAt последнего элемента предыдущей страницы (ISO 8601); используйте значение nextCursor. |
status | string | — | Фильтр: PENDING | PROCESSING | SUCCEEDED | FAILED. |
modelId | string | — | Один или несколько modelSlug через запятую. Прежние идентификаторы моделей по-прежнему принимаются. |
Ответ 200 OK
{
"items": [
{
"id": "0192...",
"modelSlug": "gpt-image-2-text-to-image",
"modelId": "legacy-model-id",
"status": "SUCCEEDED",
"outputUrls": ["..."],
"createdAt": "..."
}
],
"nextCursor": "2026-07-01T12:00:39.000Z"
}
Когда nextCursor равен null — страниц больше нет.
modelId в элементах ответа устарел и сохранён для совместимости; используйте modelSlug.
GET /v1/generations/models
Возвращает модели, которые встречаются в истории пользователя, и число генераций по каждой из них.
{
"models": [
{
"id": "legacy-model-id",
"slug": "gpt-image-2-text-to-image",
"name": "GPT Image 2",
"count": 3
}
]
}
Поле id устарело и сохранено для совместимости; используйте slug.
Discovery: slug и параметры
Список моделей, их публичные slug'и, дефолтные параметры и JSON-схему параметров отдаёт публичный каталог (без авторизации):
curl https://api.iskragen.ru/v1/catalog
{
"total": 22,
"models": [
{
"slug": "gpt-image-2-text-to-image",
"displayName": "GPT Image 2",
"mediaType": "IMAGE",
"sellPriceRub": 6,
"supportsImg2Img": true,
"defaultParams": { "aspect_ratio": "auto", "resolution": "1K" },
"paramsSchema": { "...": "..." }
}
]
}
slug→ это значение и естьmodelSlugдляPOST /v1/generations.defaultParams— что подставится, если вы не передали поле вparams.paramsSchema— допустимые ключи и значенияparamsдля конкретной модели.
Те же данные человекочитаемо есть в каталоге /models и в карточке каждой модели.
aspect_ratio vs width/height
Это частый источник путаницы. Правило простое:
- Актуальный каталог задаёт размер через
params:params.aspect_ratio— соотношение сторон ("1:1","16:9","9:16","4:3","3:4","21:9","5:4","3:2","4:5","2:3","auto").params.resolution— качество ("1K","2K","4K"). Влияет на цену.- Верхнеуровневые
width/heightэтими моделями игнорируются.
- Часть прежних пиксельных моделей использует верхнеуровневые
width/heightв пикселях.
Что поддерживает конкретная модель — смотрите в paramsSchema из каталога или в карточке модели. params всегда переопределяют defaultParams; опущенные поля берутся из дефолтов модели.
aspect_ratio: "auto"→ только1K. В режимеautoдоступно единственное разрешение1K; комбинацияauto+2K/4Kне поддерживается. Задайте явное соотношение сторон, если нужно 2K/4K.
Image-to-image: передача референса
Референс не передаётся в теле POST /v1/generations напрямую. Файл загружается одним запросом POST /v1/files, а url из ответа подставляется в params генерации.
Шаг 1 — загрузить файл: POST /v1/files
curl -X POST https://api.iskragen.ru/v1/files \
-H "Authorization: Bearer isk_live_..." \
-F "file=@reference.png"
Тело — multipart/form-data с ровно одним файловым полем file; нефайловые поля игнорируются. Авторизация — API-ключ или сессия.
Ответ 201:
{
"id": "01991d2e-7b1a-7c3e-9f00-3d2a1b4c5d6e",
"url": "https://s3.twcstorage.ru/iskragen-inputs/prod/<userId>/inputs/<uuid>.png",
"contentType": "image/png",
"sizeBytes": 123456,
"originalFilename": "reference.png",
"createdAt": "2026-09-07T12:00:00.000Z"
}
url подставляется в params генерации как есть.
Типы: image/png, image/jpeg, image/webp, image/bmp, image/tiff, image/gif, video/mp4, video/quicktime, audio/mpeg (mp3), audio/wav. Содержимое сверяется с заявленным типом по сигнатуре.
Лимиты: изображения — 30 МБ, аудио — 50 МБ, видео — 100 МБ (десятичные МБ). Не больше 20 запросов в минуту и не больше 3 одновременных загрузок на пользователя.
Ошибки (стандартный конверт { "error": { "code", "message", "requestId", "timestamp" } }):
| Код | code | Когда |
|---|---|---|
| 400 | VALIDATION_ERROR | тело не multipart; поля file нет или их два; тип не поддерживается; содержимое не совпадает с заявленным типом; пустой файл; «Файл больше N МБ» |
| 401 | AUTHENTICATION_ERROR | нет API-ключа или сессии |
| 429 | RATE_LIMIT_ERROR | превышены 20 запросов в минуту или 3 одновременные загрузки |
| 502 | STORAGE_UPLOAD_FAILED | хранилище недоступно, повторите запрос |
Шаг 2 — создать генерацию, передав url в params
Имя поля зависит от модели (смотрите paramsSchema в каталоге / карточку модели). Для image-to-image моделей это обычно input_urls (массив ссылок):
curl -X POST https://api.iskragen.ru/v1/generations \
-H "Authorization: Bearer $ISKRAGEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"modelSlug": "gpt-image-2-image-to-image",
"prompt": "Тот же кот, но в стиле акварели",
"params": {
"input_urls": ["https://s3.twcstorage.ru/iskragen-inputs/prod/<userId>/inputs/<uuid>.png"],
"aspect_ratio": "1:1",
"resolution": "1K"
}
}'
Дальше — обычный polling GET /v1/generations/:id.
Альтернатива: прямая загрузка через presigned URL
Нужна, если файл заливается напрямую из браузера или клиента в хранилище, минуя API.
Получить presigned URL
curl -X POST https://api.iskragen.ru/v1/uploads/presign-input \
-H "Authorization: Bearer $ISKRAGEN_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "contentType": "image/png", "size": 812345 }'
Ответ 200:
{
"url": "https://s3.twcstorage.ru/...&X-Amz-Signature=...",
"key": "users/<userId>/inputs/<uuid>.png",
"finalUrl": "https://s3.twcstorage.ru/.../inputs/<uuid>.png",
"expiresIn": 900
}
contentType— MIME файла (image/jpeg,image/png,image/webp,image/bmp,image/tiff,image/gif).size— размер в байтах (лимит 30 МБ).urlживётexpiresInсекунд (15 минут).
Загрузить файл (PUT)
curl -X PUT "$PRESIGNED_URL" \
-H "Content-Type: image/png" \
--data-binary @reference.png
После PUT в params генерации уходит finalUrl из ответа presign — шаг 2 дальше без изменений.
Исключение — референс-видео моделей Seedance (ниже): файл из presigned-загрузки для них не подходит.
Референс-видео у Seedance 2, Seedance 2 Fast и Seedance 2.5
params.reference_video_urls — массив ссылок на видео, загруженные через POST /v1/files. Длительность каждого ролика сервер измеряет при загрузке; сторонние ссылки и файлы из POST /v1/uploads/presign-input не принимаются. Суммарная длительность входа — не больше 15 секунд у Seedance 2 и Seedance 2 Fast и не больше 30 секунд у Seedance 2.5. Одна и та же ссылка, переданная дважды, считается дважды.
Провайдер тарифицирует и выход, и вход, поэтому цена с референс-видео считается так:
цена = цена_без_референса × (вход + выход) / выход × коэффициент_модели
вход— суммарная длительность референс-видео в секундах, округлённая вверх до целой секунды;выход— длительность клипа (params.duration);- коэффициент: Seedance 2 —
0.610, Seedance 2 Fast —0.605, Seedance 2.5 —0.603.
Пример: клип 5 секунд и референс 15 секунд — цена_без_референса × 20 / 5 × 0.61, то есть в 2,44 раза дороже того же клипа без референса. Сумма округляется до копеек и возвращается в costRub ответа.
Ошибки
Ошибки возвращаются в едином формате (подробнее — Errors):
{
"error": {
"code": "INSUFFICIENT_BALANCE",
"message": "Insufficient balance",
"requestId": "req_...",
"timestamp": "2026-07-01T12:00:00.000Z"
}
}
Коды, специфичные для Generations API:
| HTTP | code | Когда |
|---|---|---|
| 400 | VALIDATION_ERROR | Некорректное тело: пустой prompt, width/height вне диапазона и т.п. |
| 400 | REFERENCE_VIDEO_NOT_UPLOADED | Ссылка в reference_video_urls не ведёт на ваш файл из POST /v1/files (сторонний URL, чужой файл, файл из presign-input). |
| 400 | REFERENCE_VIDEO_NOT_A_VIDEO | В reference_video_urls передан ваш файл, но не видео. |
| 400 | REFERENCE_VIDEO_DURATION_UNKNOWN | Длительность ролика не удалось определить при загрузке — перезагрузите файл. |
| 400 | REFERENCE_VIDEO_TOO_LONG | Суммарная длительность референс-видео больше лимита модели. |
| 400 | REFERENCE_VIDEO_TOO_MANY | В reference_video_urls больше 10 ссылок. |
| 401 | AUTHENTICATION_ERROR | Нет/неверный API-ключ. |
| 402 | INSUFFICIENT_BALANCE | Не хватает средств. В details — required и available. |
| 403 | MODEL_NOT_AVAILABLE | Модель существует, но недоступна для новых генераций (не в публичном каталоге). |
| 404 | NOT_FOUND | Модель по modelSlug не найдена, либо id генерации чужой/несуществующий. |
| 429 | RATE_LIMIT_ERROR | Превышен лимит 5 одновременных генераций (PENDING+PROCESSING). Дождитесь завершения текущих. |
Что дальше
- Webhooks — уведомления вместо polling'а для длинных задач.
- Errors — полный формат ошибок и коды.
- Rate limits — лимиты запросов и конкурентности.
- Interactive API Reference — все эндпоинты с тестированием в браузере.