API

REST поверх HTTPS, JSON в запросах и ответах, даты в ISO 8601 (UTC). Базовый адрес: {{origin}}/v1. Ключ создаётся в кабинете, для работы нужна активная подписка.

Быстрый старт

curl {{origin}}/v1/images \
  -H "Authorization: Bearer sk-genaro-…" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "рыжий кот в шлеме космонавта, студийный свет", "model": "genaro-fast", "wait": true}'

Ответ (задание завершено, wait: true):

{
  "data": [{
    "id": "img_3f9c1a2b7d4e5f6a8b90",
    "object": "image.job",
    "status": "succeeded",
    "model": "genaro-fast",
    "prompt": "рыжий кот в шлеме космонавта, студийный свет",
    "aspect_ratio": "1:1",
    "upscale": false,
    "credits": 1,
    "created": "2026-11-06T12:00:00Z",
    "finished": "2026-11-06T12:00:48Z",
    "source": "api",
    "expired": false,
    "error": null,
    "images": [{"url": "{{origin}}/i/3f9c1a2b7d4e5f6a8b90.jpg", "thumbnail_url": "{{origin}}/i/3f9c1a2b7d4e5f6a8b90.t.webp", "width": 1024, "height": 1024}]
  }]
}

Обычно генерация занимает около 30 секунд, в 9 случаях из 10 укладывается в 70 секунд, изредка идёт дольше. В рабочих интеграциях используйте вебхук или опрос, а не долгое ожидание соединения.

Авторизация

Передавайте ключ в заголовке Authorization: Bearer sk-genaro-… или X-API-Key: sk-genaro-…. Ключ привязан к аккаунту и тратит его кредиты. Ключ показывается один раз при создании, на аккаунт можно держать до 10 ключей. Держите ключ на сервере: в браузере и мобильных приложениях он виден всем. Скомпрометированный ключ отзывается в кабинете. Без ключа работают только GET /v1/models и ссылки на готовые файлы.

Модели и кредиты

В запросах указывается id, в таблице рядом показана реальная модель, которая выполняет генерацию. Стоимость задания в кредитах списывается из часового лимита тарифа.

idРеальная модельДля чегоКредитовС апскейлом ×2

Форматы: 1:1, 16:9, 9:16, 4:3, 3:4. Длинная сторона результата обычно 1–1,4K, точный размер приходит в полях width и height. Апскейл ×2 доступен моделям с supports_upscale.

GET /v1/models

{
  "data": [{
    "id": "genaro-pro",
    "label": "Genaro Pro",
    "underlying_model": "Nano Banana Pro (Google)",
    "description": "Лучшее качество: надписи на картинке, портреты, работа по референсу.",
    "credits": 4,
    "credits_upscale": 8,
    "supports_upscale": true,
    "aspects": ["1:1", "16:9", "9:16", "4:3", "3:4"]
  }]
}

Тарифы и лимиты

ТарифЦенаКредитов в часМаксимум за периодЗаданий одновременно

Создать изображение

POST /v1/images → 202 Accepted, или 200 при wait: true, если все задания успели завершиться. В ответе массив data с объектами заданий.

ПолеТипОписание
promptstringОбязательное. Описание, до 4000 символов. Русский и английский.
modelstringПо умолчанию genaro-fast.
aspect_ratiostringПо умолчанию 1:1.
nint1–4. Каждая картинка — отдельное задание со своей ценой и id. Цена резервируется за все сразу.
upscaleboolАпскейл ×2, цена ×2. Только для моделей с поддержкой.
seedintОт 0 до 2147483647. Для повторяемости, если модель поддерживает.
reference_imagesstring[]До 4 референсов: JPEG, PNG, WebP или GIF в base64 либо data:image/…;base64,…, до 6 МБ и 50 млн пикселей каждый. Метаданные (EXIF) удаляются, после задания файлы не хранятся.
webhook_urlstringПубличный URL, куда придёт готовое задание.
waitboolЖдать результат в этом же запросе, по умолчанию false.
timeoutintСколько секунд ждать при wait: 5–300, по умолчанию 120. Если время вышло, ответ 202 с текущим статусом.

Python, референс и ожидание результата:

import base64, requests

ref = base64.b64encode(open("face.jpg", "rb").read()).decode()
r = requests.post("{{origin}}/v1/images",
    headers={"Authorization": "Bearer sk-genaro-…"},
    json={"prompt": "этот же человек в деловом костюме, офис", "model": "genaro-pro",
          "aspect_ratio": "3:4", "reference_images": [ref], "wait": True},
    timeout=320)
job = r.json()["data"][0]
print(job["status"], job["images"][0]["url"] if job["images"] else job["error"])

JavaScript, задание с вебхуком:

const r = await fetch("{{origin}}/v1/images", {
  method: "POST",
  headers: { Authorization: "Bearer sk-genaro-…", "Content-Type": "application/json" },
  body: JSON.stringify({
    prompt: "уютная кофейня, тёплый свет",
    model: "genaro-plus",
    aspect_ratio: "16:9",
    webhook_url: "https://example.com/hook?token=секрет",
  }),
});
const { data } = await r.json();
console.log(data[0].id, data[0].status);

Объект задания

ПолеТипОписание
idstringИдентификатор вида img_….
objectstringВсегда image.job.
statusstringqueued, running, succeeded, failed, canceled.
model, prompt, aspect_ratio, upscaleПараметры запроса.
creditsintСтоимость задания.
created, finishedstringВремя создания и завершения, finished пустое до конца работы.
sourcestringapi, compat или web.
queue_positionintМесто в очереди, только при queued.
imagesarrayurl, thumbnail_url (webp), width, height. Пусто, пока нет результата и после удаления файлов.
expiredbooltrue, если файлы удалены вами или по сроку хранения.
errorobject{"code": "generation_failed", "message": "…"} при failed, иначе null.

Получить результат

Без wait опрашивайте GET /v1/images/{id} раз в 2–3 секунды или используйте вебхук.

while True:
    j = requests.get(f"{{origin}}/v1/images/{job_id}", headers=H).json()
    if j["status"] in ("succeeded", "failed", "canceled"):
        break
    time.sleep(2)

Ссылки на изображения не требуют ключа: не публикуйте их, если картинка приватная. Статус failed означает, что кредиты вернулись в лимит часа, причина лежит в error. Запрос можно отправить снова.

Список заданий

GET /v1/images?limit=20&before=ID отдаёт ваши задания, новые первыми. limit 1–100, по умолчанию 20. Для следующей страницы передайте в before id последнего элемента.

{"data": [ /* объекты заданий */ ], "has_more": true}

Отмена и удаление

POST /v1/images/{id}/cancelОтменяет задание в очереди, кредиты возвращаются. Ответ — объект задания. Задание в работе отменить нельзя: 409 not_cancellable.
DELETE /v1/images/{id}Удаляет файлы завершённого задания. Ответ: {"id": "img_…", "deleted": true}. Для незавершённого: 409 in_progress.

Остаток кредитов

GET /v1/usage

{
  "source": "subscription",
  "credits_per_hour": 250,
  "credits_used": 12,
  "credits_left": 238,
  "window_resets_at": "2026-11-06T13:00:00Z",
  "subscription_ends": "2026-12-06T12:00:00Z",
  "plan": "Про"
}

Без активной подписки source равен none, а новые задания получают 402 subscription_required.

Вебхуки

Если указан webhook_url, после завершения (успех или ошибка) мы отправим POST с JSON задания: это тот же объект, что возвращает GET /v1/images/{id}. Ответ с кодом меньше 500 считается доставкой, при ошибке будет до трёх попыток: сразу, через 5 и через 30 секунд. Адрес должен быть публичным, порты только 80, 443, 8080 и 8443, локальные и внутренние сети блокируются, редиректы не выполняются, ответа мы ждём до 10 секунд.

Подписи у вебхуков нет. Чтобы убедиться, что вызов настоящий, зашейте секрет в URL (…/hook?token=…) и перепроверяйте статус через GET.

Идемпотентность

Передайте заголовок Idempotency-Key: <уникальная строка> в POST /v1/images. Повтор запроса с тем же ключом вернёт те же задания и ничего не спишет второй раз, так что повторять при таймаутах сети безопасно.

OpenAI-совместимость

POST /v1/images/generations повторяет формат OpenAI Images API и всегда ждёт результат, до 170 секунд. Работают OpenAI SDK и no-code платформы (n8n, Make, Flowise): укажите наш адрес как базовый и ваш ключ.

ПолеОписание
promptОбязательное.
modelНаш id. Также принимаются dall-e-3 (→ genaro-pro), dall-e-2 (→ genaro-fast), gpt-image-1 (→ genaro-text). По умолчанию genaro-fast.
n1–4.
sizeНапример 1792x1024, переводится в ближайший формат.
response_formaturl (по умолчанию) или b64_json.
qualityПринимается и не влияет на результат.
curl {{origin}}/v1/images/generations \
  -H "Authorization: Bearer sk-genaro-…" \
  -H "Content-Type: application/json" \
  -d '{"model": "genaro-pro", "prompt": "уютная кофейня, тёплый свет", "size": "1792x1024"}'
from openai import OpenAI

client = OpenAI(base_url="{{origin}}/v1", api_key="sk-genaro-…")
image = client.images.generate(model="genaro-pro", prompt="уютная кофейня, тёплый свет", size="1792x1024")
print(image.data[0].url)

Ответ: {"created": 1762430400, "data": [{"url": "…", "revised_prompt": "…"}]}. Если генерация не успела, вернётся 504 timeout с полем job_id: заберите результат через GET /v1/images/{id}.

Ошибки

Тело ошибки: {"error": {"code": "...", "type": "...", "message": "..."}}. Текст сообщения можно показывать пользователю, логику стоит строить по code.

HTTPcodeКогдаЧто делать
400invalid_requestНеверные параметры, сообщение указывает поле.Исправить запрос.
400invalid_modelНет такой модели.Взять id из /v1/models.
400content_policyЗапрос отклонён фильтром.Изменить запрос. Пять нарушений блокируют аккаунт.
401missing_api_key, invalid_api_keyНет ключа или он отозван.Проверить ключ.
402subscription_requiredНет активной подписки.Оформить или продлить.
403email_not_verifiedПочта не подтверждена.Открыть ссылку из письма.
403account_suspendedАккаунт заблокирован.Написать в поддержку.
404not_foundНет такого задания у этого аккаунта.Проверить id.
409not_cancellable, in_progressДействие невозможно в текущем статусе.Дождаться завершения.
413payload_too_largeТело запроса больше 40 МБ.Уменьшить референсы.
429quota_exceededНе хватает кредитов часа.Ждать Retry-After.
429rate_limitedСлишком много запросов.Ждать Retry-After, снизить частоту.
502generation_failedМодель не справилась, только в совместимом методе.Повторить, кредиты вернулись.
503service_unavailable, busyСервис недоступен или очередь переполнена.Повторить позже.
504timeoutСовместимый метод не дождался результата.Забрать по job_id.

В основном API отказ модели приходит статусом failed у задания (чтение при этом отвечает 200), а кредиты возвращаются.

Правила использования

Запрещены откровенный контент для взрослых, любые сексуальные сцены с участием несовершеннолетних, дипфейки реальных людей без согласия, мошенничество и нарушение прав третьих лиц. Подробности — в условиях использования. Не перепродавайте и не публикуйте свой ключ.