IskraGen

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

Создать генерацию.

Тело запроса

ПолеТипОбяз.Описание
modelSlugstringдаПубличный slug модели IskraGen (например gpt-image-2-text-to-image). Источник правды — каталог (раздел «Discovery» ниже) и «ID модели» в карточке модели.
promptstringдаОт 1 символа. Верхняя граница зависит от модели: по умолчанию 4000 символов, у отдельных моделей меньше или больше. Актуальное значение — поле promptMaxChars модели в GET /v1/catalog; абсолютный максимум запроса — 10 000 символов. Превышение лимита модели возвращает VALIDATION_ERROR (400) с details.reason: "PROMPT_TOO_LONG", details.limit и details.actual; деньги не списываются.
negativePromptstringнетДо 2000 символов.
paramsobjectнетПараметры, специфичные для модели (например aspect_ratio, resolution, duration, input_urls). Мёрджатся поверх defaultParams модели. См. раздел «aspect_ratio vs width/height» ниже.
widthintegerнет256–4096. Только для части прежних пиксельных моделей. Для актуального каталога используйте params.aspect_ratio + params.resolution.
heightintegerнет256–4096. См. width.
durationSecintegerнет1–600. Длительность для видео/аудио, если модель принимает секунды.
seedintegerнет≥ 0. Для воспроизводимости.
idempotencyKeystringнет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"
}
ПолеТипОписание
modelSlugstringПубличный идентификатор модели.
modelIdstringУстарело. Внутренний идентификатор; используйте modelSlug.
statusstringPENDING | PROCESSING | SUCCEEDED | FAILED | REFUNDED | CANCELLED | ENQUEUE_FAILED.
outputUrlsstring[]Ссылки на результат (S3). Пусто, пока status ≠ SUCCEEDED.
errorCode / errorMessagestring | nullЗаполняются при FAILED.
mediaPriceRubnumber | nullРеальная цена медиа (когда доступна).
chargeStatusstring | nullТехнический статус биллингового контура. null — контур для вашего аккаунта не задействован (текущий режим по умолчанию): списание и возврат уже произошли, но отдельного статуса для них нет — ориентируйтесь на status и баланс. Если контур включён, возможные значения — PENDING / CHARGED / RELEASED / FAILED / FAILED_EXPIRED.
startedAt / finishedAtstring | nullISO-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-параметры

ПараметрТипПо умолчаниюОписание
indexinteger0Номер файла результата, от 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

Ошибки:

HTTPcodeКогда
404NOT_FOUNDГенерации нет, она принадлежит другому пользователю или у неё нет файла с таким index.
502OUTPUT_FETCH_FAILEDФайл не удалось получить из хранилища.

GET /v1/generations

Список генераций пользователя, cursor-пагинация (новые первыми).

Query-параметры

ПараметрТипПо умолчаниюОписание
limitinteger201–100.
cursorstring—createdAt последнего элемента предыдущей страницы (ISO 8601); используйте значение nextCursor.
statusstring—Фильтр: PENDING | PROCESSING | SUCCEEDED | FAILED.
modelIdstring—Один или несколько 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Когда
400VALIDATION_ERRORтело не multipart; поля file нет или их два; тип не поддерживается; содержимое не совпадает с заявленным типом; пустой файл; «Файл больше N МБ»
401AUTHENTICATION_ERRORнет API-ключа или сессии
429RATE_LIMIT_ERRORпревышены 20 запросов в минуту или 3 одновременные загрузки
502STORAGE_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:

HTTPcodeКогда
400VALIDATION_ERRORНекорректное тело: пустой prompt, width/height вне диапазона и т.п.
400REFERENCE_VIDEO_NOT_UPLOADEDСсылка в reference_video_urls не ведёт на ваш файл из POST /v1/files (сторонний URL, чужой файл, файл из presign-input).
400REFERENCE_VIDEO_NOT_A_VIDEOВ reference_video_urls передан ваш файл, но не видео.
400REFERENCE_VIDEO_DURATION_UNKNOWNДлительность ролика не удалось определить при загрузке — перезагрузите файл.
400REFERENCE_VIDEO_TOO_LONGСуммарная длительность референс-видео больше лимита модели.
400REFERENCE_VIDEO_TOO_MANYВ reference_video_urls больше 10 ссылок.
401AUTHENTICATION_ERRORНет/неверный API-ключ.
402INSUFFICIENT_BALANCEНе хватает средств. В details — required и available.
403MODEL_NOT_AVAILABLEМодель существует, но недоступна для новых генераций (не в публичном каталоге).
404NOT_FOUNDМодель по modelSlug не найдена, либо id генерации чужой/несуществующий.
429RATE_LIMIT_ERRORПревышен лимит 5 одновременных генераций (PENDING+PROCESSING). Дождитесь завершения текущих.

Что дальше

  • Webhooks — уведомления вместо polling'а для длинных задач.
  • Errors — полный формат ошибок и коды.
  • Rate limits — лимиты запросов и конкурентности.
  • Interactive API Reference — все эндпоинты с тестированием в браузере.
Generations API · IskraGen Docs — IskraGen