Images
POST /v1/generations
Creates an asynchronous generation job. Credits are reserved immediately and refunded if the job fails.
Headers
| 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 |
Body
| 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. |
Response 202 Accepted
{"id": "…", "model": "nanobanana", "status": "queued", "params": {…}, "cost": 2, "created_at": "…"}Body size limit 64 KB. Unknown fields are rejected with 400.
GET /v1/generations/{id}
Returns the job. When status = succeeded the response includes images[] with presigned download URLs (15 minutes; call again for fresh URLs).
| 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, …}Chat completions are stored as generations too: the record carries capability: "text.chat" and a usage block with the token counts — never the messages themselves, only a ≤ 200-character preview of the last user message and a hash.
{"id": "…", "model": "qwen3.8-max", "capability": "text.chat", "status": "succeeded", "params": {"prompt": "Explain idempotency keys…", "messages": 2, "messages_sha256": "9f2c…", "max_tokens": 200, "stream": true}, "usage": {"prompt_tokens": 31, "completion_tokens": 58, "total_tokens": 89, "finish_reason": "stop", "usage_source": "estimated"}, "cost": 0.004, "created_at": "…", "finished_at": "…"}GET /v1/generations
Newest first, 50 per page. Pass cursor from the previous response to get the next page.
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"}Filter by kind with ?capability=text.chat (or image.generate).
DELETE /v1/generations/{id}
Cancels a job that is still queued and refunds its credits. Jobs that are already running cannot be cancelled (409).
curl -s -X DELETE https://api.genmux.tech/v1/generations/<id> -H "Authorization: Bearer $API_KEY"{"id": "…", "status": "cancelled", …}