Справочник API
Базовый URL https://api.genmux.tech. Все запросы и ответы — JSON. Каждому запросу нужен API-ключ.
Быстрый старт
Создайте ключ в кабинете, экспортируйте его и выполните команды в точности как показано.
export API_KEY=nb_live_... # from Dashboard → API keys1. Отправьте задание
curl -s -X POST https://api.genmux.tech/v1/generations \
-H "Authorization: Bearer $API_KEY" \
-H "Idempotency-Key: $(uuidgen)" \
-H "Content-Type: application/json" \
-d '{"model":"nanobanana","prompt":"a red fox in snow","resolution":"1K","ratio":"1:1"}'{
"id": "0d8b6a3e-2f1c-4a5b-9c1d-7e2f3a4b5c6d",
"model": "nanobanana",
"status": "queued",
"params": {"prompt": "a red fox in snow", "n": 1, "resolution": "1K", "ratio": "1:1"},
"cost": 2,
"created_at": "2026-08-28T20:01:12.345Z"
}2. Опрашивайте, пока status = succeeded (обычно 1–20 с)
curl -s https://api.genmux.tech/v1/generations/0d8b6a3e-2f1c-4a5b-9c1d-7e2f3a4b5c6d \
-H "Authorization: Bearer $API_KEY"{
"id": "0d8b6a3e-2f1c-4a5b-9c1d-7e2f3a4b5c6d",
"model": "nanobanana",
"status": "succeeded",
"params": {"prompt": "a red fox in snow", "n": 1, "resolution": "1K", "ratio": "1:1"},
"cost": 2,
"images": [
{
"index": 0,
"url": "https://…/0.png?X-Amz-Expires=900&…",
"expires_at": "2026-08-28T20:16:30Z",
"mime": "image/png",
"width": 1024,
"height": 1024,
"bytes": 1843201,
"sha256": "9f2c…"
}
],
"created_at": "2026-08-28T20:01:12.345Z",
"finished_at": "2026-08-28T20:01:19.802Z"
}3. Скачайте изображение (ссылка действует 15 минут)
curl -s -o fox.png "https://…/0.png?X-Amz-Expires=900&…"Аутентификация
Передавайте ключ как bearer-токен. Ключи начинаются с nb_live_, показываются один раз при создании, их можно ротировать и отзывать в кабинете.
Authorization: Bearer $API_KEYОпциональный список IP для ключа: запросы с других адресов получают 403 ip_not_allowed.
POST /v1/generations
Создаёт асинхронное задание генерации. Кредиты резервируются сразу и возвращаются, если задание не удалось.
Заголовки
| Header | Required | Description |
|---|---|---|
| Authorization | yes | Bearer <API key> |
| Idempotency-Key | yes | Unique per request (≤ 128 chars). Resending the same key returns the original job (200) without charging again. Same key with a different body → 422. |
| Content-Type | yes | application/json |
Тело
| Field | Type | Description |
|---|---|---|
| model | string | Required. A model id from GET /v1/models, e.g. "nanobanana". |
| prompt | string | Required unless images is present. 1–2000 characters (a model may cap it lower — see max_prompt). |
| negative_prompt | string | Optional. What to steer away from. Only on models whose schema has negative_prompt: true. |
| n | integer | Images to generate, 1–4. Default 1. Each image is billed separately. |
| resolution | string | 1K (default) · 2K · 4K. The tier a model renders at, and the unit it is priced in. A model lists the tiers it supports in params_schema.resolutions. |
| ratio | string | Aspect ratio: auto · 1:1 (default) · 16:9 · 9:16 · 4:3 · 3:4 · 3:2 · 2:3 · 5:4 · 4:5 · 21:9. Ratio never changes the price. |
| images | string[] | Optional. Reference images for image-to-image, as public https URLs. Up to the model's max_images; omitted from a model's schema means it does not accept them. |
| seed | integer | Optional. Same seed + prompt gives a reproducible result when the model supports it. |
| webhook_url | string | Optional https URL called when the job finishes. See Webhooks. |
| size | string (legacy) | Deprecated. A WIDTHxHEIGHT string, mapped to the nearest resolution + ratio. Accepted for existing integrations only; sending it together with resolution or ratio is a 400. New code should use resolution and ratio. |
Ответ 202 Accepted
{"id": "…", "model": "nanobanana", "status": "queued", "params": {…}, "cost": 2, "created_at": "…"}Лимит размера тела 64 КБ. Неизвестные поля отклоняются с 400.
GET /v1/generations/{id}
Возвращает задание. Когда status = succeeded, ответ содержит images[] с временными ссылками на скачивание (15 минут; повторите запрос для свежих ссылок).
| status | Meaning |
|---|---|
| queued | Waiting for a worker. |
| running | Being generated. |
| succeeded | Done; images[] present; credits captured. |
| failed | Failed; error{code,message} present; credits refunded. |
| cancelled | Cancelled by you before it started; credits refunded. |
{"id": "…", "status": "failed", "error": {"code": "content_policy", "message": "the prompt was rejected by the content policy"}, "cost": 2, …}GET /v1/generations
Сначала новые, по 50 на страницу. Передайте cursor из предыдущего ответа, чтобы получить следующую.
curl -s "https://api.genmux.tech/v1/generations?cursor=2026-08-28T20:01:12.345Z" -H "Authorization: Bearer $API_KEY"{"data": [ {…job…}, … ], "next_cursor": "2026-08-27T09:12:44.001Z"}DELETE /v1/generations/{id}
Отменяет задание в статусе queued и возвращает кредиты. Уже выполняющиеся задания отменить нельзя (409).
curl -s -X DELETE https://api.genmux.tech/v1/generations/<id> -H "Authorization: Bearer $API_KEY"{"id": "…", "status": "cancelled", …}GET /v1/account
curl -s https://api.genmux.tech/v1/account -H "Authorization: Bearer $API_KEY"{
"id": "…",
"name": "…",
"balance": 498,
"inflight": 1,
"max_inflight": 20,
"key": {"prefix": "nb_live_AbCdEfGh", "rate_limit_rps": 10}
}GET /v1/models
Возвращает публичный каталог моделей — id, поддерживаемые тиры разрешения и соотношения сторон, кредиты за тир и доступность. Аутентификация не требуется.
curl -s https://api.genmux.tech/v1/models{
"data": [
{
"id": "nanobanana",
"display_name": "Nano Banana",
"description": "Fast text-to-image and image-to-image at 1K.",
"capability": "image.generate",
"status": "active",
"params_schema": {
"resolutions": ["1K"],
"ratios": ["auto", "1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "5:4", "4:5", "21:9"],
"max_n": 4,
"seed": true,
"max_images": 14,
"negative_prompt": true,
"max_prompt": 2000
},
"default_params": {"resolution": "1K", "ratio": "1:1", "n": 1},
"prices": {"image:1K": 2},
"available": true
},
{
"id": "nanobanana-pro",
"display_name": "Nano Banana Pro",
"description": "Higher fidelity, with 1K, 2K and 4K output.",
"capability": "image.generate",
"status": "active",
"params_schema": {
"resolutions": ["1K", "2K", "4K"],
"ratios": ["auto", "1:1", "16:9", "9:16", "4:3", "3:4", "3:2", "2:3", "5:4", "4:5", "21:9"],
"max_n": 4,
"seed": true,
"max_images": 14,
"negative_prompt": true,
"max_prompt": 2000
},
"default_params": {"resolution": "1K", "ratio": "1:1", "n": 1},
"prices": {"image:1K": 4, "image:2K": 6, "image:4K": 8},
"available": true
}
]
}Цены заданы по тирам разрешения: image:1K, image:2K, image:4K. Модель объявляет, что принимает, в params_schema — resolutions, ratios, max_images (референсные изображения; поля нет — image-to-image не поддерживается) и negative_prompt. В каталоге может оставаться устаревший список sizes и соответствующие цены image:WIDTHxHEIGHT — они нужны только клиентам, которые всё ещё шлют поле size.
Модели и цены
Стоимость задания = кредиты за изображение (ниже) × n. Она резервируется при отправке и полностью возвращается при неудаче или отмене.
| Model | 1K long edge ~1024 px | 2K long edge ~2048 px | 4K long edge ~4096 px |
|---|---|---|---|
Nano Banana nanobanana up to 4 images per request | 2credits ≈ $0.025 / image | — | — |
Nano Banana Pro nanobanana-pro up to 4 images per request | 4credits ≈ $0.05 / image | 6credits ≈ $0.075 / image | 8credits ≈ $0.10 / image |
Qwen-Image 2.0 qwen-image-2 up to 4 images per request | 3credits ≈ $0.038 / image | 4credits ≈ $0.05 / image | — |
Qwen-Image Max qwen-image-max up to 4 images per request | 8credits ≈ $0.10 / image | 9credits ≈ $0.113 / image | — |
Seedream 5.0 seedream-5 up to 4 images per request | — | 16credits ≈ $0.20 / image | 18credits ≈ $0.225 / image |
Wan 2.7 Image wan-2-7-image up to 4 images per request | 2credits ≈ $0.025 / image | 3credits ≈ $0.038 / image | — |
Pick a tier with resolution and a shape with ratio. Money figures use the best-value pack ($0.013 per credit). Cost = credits × n; failed jobs are refunded in full.
Ошибки
Ошибки используют application/problem+json. Ориентируйтесь на code; request_id также возвращается в заголовке X-Request-ID — прилагайте его при обращении в поддержку.
{"type": "…/errors/insufficient_credits", "title": "Payment Required", "status": 402, "code": "insufficient_credits", "detail": "account balance is too low for this request", "request_id": "…"}| HTTP | code | When |
|---|---|---|
| 400 | validation_error | Bad or missing field, unknown field, missing Idempotency-Key. |
| 401 | unauthorized | Missing, revoked or expired API key. |
| 402 | insufficient_credits | Balance lower than the job cost. Buy credits in the dashboard. |
| 403 | ip_not_allowed | Key has an IP allowlist and your address is not on it. |
| 404 | not_found | Unknown job id (or it belongs to another account). |
| 404 | model_not_found | Unknown model id. See GET /v1/models for the current catalogue. |
| 409 | conflict | Job cannot be cancelled in its current state. |
| 422 | idempotency_key_mismatch | Idempotency-Key reused with a different body. |
| 429 | rate_limited | Per-key request rate exceeded. Honour Retry-After. |
| 429 | too_many_inflight | More than max_inflight jobs queued/running. Wait for some to finish. |
| 503 | model_unavailable | The model is temporarily disabled — nothing is charged. Retry later or pick another model. |
| 500 | internal_error | Our fault. Retry with the same Idempotency-Key — you will not be charged twice. |
Лимиты
У каждого ключа есть лимит запросов в секунду (по умолчанию 10), а у аккаунта — лимит одновременных заданий (по умолчанию 20). При превышении ответ 429 с заголовком Retry-After в секундах. Нужно больше? Напишите нам из кабинета.
Вебхуки
Передайте webhook_url (только https, публичный хост) при создании задания. Мы отправляем POST по завершении и повторяем с бэкоффом до 8 попыток, пока вы не вернёте 2xx.
Content-Type: application/json
X-Webhook-Id: 1042
X-Webhook-Timestamp: 1756411279
X-Webhook-Signature: v1=3f7a…
{"type": "generation.succeeded", "id": "…", "status": "succeeded", "error_code": null, "created_at": "…", "finished_at": "…"}Проверяйте подпись секретом вебхуков аккаунта (Кабинет → Настройки): HMAC-SHA256(secret, timestamp + "." + raw_body), в hex, сравнивая со значением после v1=. Во время ротации секрета приходят две подписи через запятую — принимайте любую. Отклоняйте метки времени старше 5 минут.
import { createHmac, timingSafeEqual } from "node:crypto";
export function verify(secret, headers, rawBody) {
const ts = headers["x-webhook-timestamp"];
const expected = createHmac("sha256", secret).update(ts + "." + rawBody).digest("hex");
return headers["x-webhook-signature"].split(",")
.some((s) => { const v = s.replace(/^v1=/, ""); return v.length === expected.length && timingSafeEqual(Buffer.from(v), Buffer.from(expected)); });
}