genmux API теперь доступен всем. Читать документацию →
genmux API

Блог

Генерация изображений через Nano Banana API на Python

2 мин чтенияАвтор Unified Image API Team


Полная интеграция на Python: отправка → опрос → скачивание, с идемпотентностью и обработкой ошибок, которые не стыдно выкатить в прод. Единственная зависимость — requests.

Подготовка

Создайте API-ключ в кабинете и экспортируйте его:

bash
export IMAGE_API_KEY=nb_live_...
export IMAGE_API_BASE=https://api.example.com   # ваш базовый URL из документации

Отправка задания

Генерация асинхронная: POST /v1/generations возвращает id задания за миллисекунды, изображение готово через несколько секунд. Всегда передавайте Idempotency-Key — если процесс упадёт и повторит запрос, вы получите то же задание, а не заплатите дважды.

python
import os, time, uuid, requests

BASE = os.environ["IMAGE_API_BASE"]
HEADERS = {"Authorization": f"Bearer {os.environ['IMAGE_API_KEY']}"}

def submit(prompt: str, resolution: str = "1K", ratio: str = "1:1", model: str = "nanobanana") -> dict:
    r = requests.post(
        f"{BASE}/v1/generations",
        headers={**HEADERS, "Idempotency-Key": str(uuid.uuid4())},
        json={"model": model, "prompt": prompt, "n": 1, "resolution": resolution, "ratio": ratio},
        timeout=10,
    )
    r.raise_for_status()   # 202 Accepted
    return r.json()        # {"id": "...", "status": "queued", "cost": 2, ...}

Правильный опрос

Опрашивайте с бэкоффом, а не в цикле без пауз — задания обычно завершаются за 1–20 секунд:

python
def wait(job_id: str, timeout_s: int = 120) -> dict:
    deadline, delay = time.monotonic() + timeout_s, 0.5
    while time.monotonic() < deadline:
        job = requests.get(f"{BASE}/v1/generations/{job_id}", headers=HEADERS, timeout=10).json()
        if job["status"] in ("succeeded", "failed", "cancelled"):
            return job
        time.sleep(delay)
        delay = min(delay * 1.6, 5.0)
    raise TimeoutError(job_id)

Скачивание результатов

Ссылки на изображения подписаны и истекают через 15 минут. Нужен файл позже — скачайте сразу; ссылка истекла — просто запросите задание ещё раз, придут свежие.

python
def download(job: dict, path: str) -> None:
    if job["status"] != "succeeded":
        raise RuntimeError(f"{job['status']}: {job.get('error')}")
    img = job["images"][0]
    data = requests.get(img["url"], timeout=30).content
    with open(path, "wb") as f:
        f.write(data)

job = submit("рыжая лиса в снегу, студийный свет")
job = wait(job["id"])
download(job, "fox.png")

Обработка ошибок по-взрослому

Ошибки приходят как application/problem+json; ветвитесь по code:

codeЧто делать
insufficient_credits (402)Остановить отправку; оповестить ответственного за баланс.
rate_limited / too_many_inflight (429)Подождать Retry-After секунд и повторить тот же запрос.
model_unavailable (503)Ничего не списано. Повторить позже или переключиться на другую модель.
internal_error (500)Повторить с тем же Idempotency-Key — двойного списания не будет.
Статус задания failedКредиты уже возвращены автоматически; смотрите error.code.

Последняя строка — свойство, вокруг которого стоит проектировать: неудачное задание ничего не стоит, поэтому вашей логике повторов не нужно сверять деньги — просто отправляйте заново.

Дальше: замените model на nanobanana-pro для большей детализации (сравнение) или уберите опрос в пользу вебхуков.

Об авторе

Автор Unified Image API Team — genmux API.

Подробнее о нас