Image generation
Deliverable: a generate.py and an edit.py that write a PNG to disk.
Prerequisites: pip install requests, a MIRAPI_API_KEY, and an image-capable model enabled for your key.
MirAPI exposes two OpenAI-compatible endpoints for images, both billed per generated image:
POST /v1/images/generations— text-to-image.POST /v1/images/edits— edit an image from a source image plus an instruction.
There is no separate Anthropic or Gemini image-generation endpoint — those protocols only read images back into chat models (see Vision inputs).
Text-to-image
Section titled “Text-to-image”/v1/images/generations takes a chat-style input.messages payload with a parameters object:
import base64import osimport requests
BASE = "https://api.mirapi.ai/v1"HEADERS = {"Authorization": f"Bearer {os.environ['MIRAPI_API_KEY']}"}
resp = requests.post( f"{BASE}/images/generations", headers=HEADERS, json={ "model": "deepseek-chat", "input": { "messages": [ {"role": "user", "content": [{"text": "A neon-lit street in the rain, cinematic"}]} ] }, "parameters": {"size": "1024*1024", "prompt_extend": True, "watermark": False}, }, timeout=120,)resp.raise_for_status()
image = resp.json()["data"][0]if image["b64_json"]: with open("output.png", "wb") as f: f.write(base64.b64decode(image["b64_json"]))else: open("output.png", "wb").write(requests.get(image["url"], timeout=60).content)print("Saved output.png")Edit an image
Section titled “Edit an image”/v1/images/edits sends the source image and the instruction in the same message-style shape. The image field accepts a public HTTP(S) URL or a base64 data URI:
import base64import osimport requests
BASE = "https://api.mirapi.ai/v1"HEADERS = {"Authorization": f"Bearer {os.environ['MIRAPI_API_KEY']}"}
# A base64 data URI of the source image:with open("input.png", "rb") as f: data_uri = "data:image/png;base64," + base64.b64encode(f.read()).decode()
resp = requests.post( f"{BASE}/images/edits", headers=HEADERS, json={ "model": "deepseek-chat", "input": { "messages": [ { "role": "user", "content": [ {"image": data_uri}, {"text": "Turn the sky into a starry night"}, ], } ] }, "parameters": {"n": 1, "watermark": False}, }, timeout=120,)resp.raise_for_status()
image = resp.json()["data"][0]if image["b64_json"]: with open("edited.png", "wb") as f: f.write(base64.b64decode(image["b64_json"]))else: open("edited.png", "wb").write(requests.get(image["url"], timeout=60).content)print("Saved edited.png")The two request shapes
Section titled “The two request shapes”The image endpoints accept two payload formats:
- Message-style —
/v1/images/generationsand/v1/images/edits(no trailing slash). Usesinput.messagesplusparameters, as in the scripts above. - OpenAI classic — the trailing-slash variants
/v1/images/generations/and/v1/images/edits/. Uses a top-levelpromptfor OpenAI SDK compatibility; edits sendimage+promptas multipart form data.
curl https://api.mirapi.ai/v1/images/generations/ \ -H "Authorization: Bearer $MIRAPI_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "deepseek-chat", "prompt": "A neon-lit street in the rain, cinematic", "n": 1, "size": "1024x1024" }'The classic edits variant uses multipart/form-data with an image file, a prompt, and response_format (url or b64_json).
Parameters
Section titled “Parameters”Message-style requests put everything under parameters:
| Parameter | Purpose |
|---|---|
model |
Model name exactly as shown in the catalogue |
input.messages[].content[].text |
The generation or edit instruction |
input.messages[].content[].image |
Source image for edits (URL or base64 data URI) |
parameters.size |
Output dimensions as a string, e.g. 1024*1024 |
parameters.negative_prompt |
Things to avoid in the output |
parameters.prompt_extend |
Let the model expand the prompt (true / false) |
parameters.watermark |
Request a visible watermark (true / false) |
parameters.n |
Number of images to return (edits; where supported) |
Not every model accepts every parameter, and many models only support n: 1 — check the model card in the catalogue for supported values.
Retrieving the image
Section titled “Retrieving the image”The response contains an array of images:
{ "created": 1780000000, "data": [ { "url": "https://…", "b64_json": null, "revised_prompt": "…" } ]}url— a temporary URL to download the image.b64_json— the image as a base64 string.revised_prompt— the prompt actually used when the model rewrites yours.
To save the image to disk, prefer b64_json (no second request) or download url immediately — it is temporary.
Errors and billing
Section titled “Errors and billing”Billing. Generation and editing are charged per image, deducted from your prepaid balance; parameters.n multiplies the cost, so start with n: 1. When the balance is exhausted, requests return 403; topping up restores the same key immediately. Reconcile spend in the console billing log, or via GET /api/usage/token (account summary) and GET /api/log/token (per-request detail).
Errors. The gateway returns standard status codes: 401 (fix your key), 403 (balance, model whitelist, quota, or IP allowlist), 413 (request too large), 429 (rate limited — retry with jittered exponential backoff, 1s → 2s → 4s capped at ~30s; there is no Retry-After header), and 500 (transient upstream failure; idempotent requests are safe to retry). Error responses use the OpenAI envelope {"error":{"message","type","param","code"}}, and every message ends with a request ID — include it in any support ticket.
Troubleshooting
Section titled “Troubleshooting”- Wrong model. Image endpoints reject models without image-generation capability. Filter the catalogue by output type and use the model’s exact
id. 403on a valid key. Check your balance first, then the model whitelist, quota, and IP allowlist on the key.urlno longer works. Download it immediately after the request, or useb64_json.413with base64. Large images exceed the size limit — downscale before encoding.nignored or rejected. Some models return a single image regardless; check the model card.
Related links
Section titled “Related links”- Image generation guide — the endpoints in full
- Vision inputs — read images back into chat models
- Text-to-video — the asynchronous video flow
- Image-to-video — first-frame control
- Models & pricing — find image-capable models
- Billing & top-ups — per-image and per-token pricing