API reference
Image studio (company keys)
Make an image from a prompt, or change your own photo, with the Nano Banana 2 model at 512 × 512 pixels. For companies that bought the Image studio: every image comes out of an image pack you bought once.
403 KEY_SCOPE. An Image studio key opens only the paths under /v1/studio/images/, nothing else.Generate an image
Send a JSON body with a prompt and, to edit your own photo, one or more reference images. The reply holds the image as base64 and what is left in your pack.
curl https://acacus.ly/v1/studio/images/generate \
-H "Authorization: Bearer $ACACUS_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: order-1001" \
-d '{
"prompt": "The same bag on a clean white background, soft shadow",
"reference_images": ["data:image/jpeg;base64,'"$(base64 -w0 bag.jpg)"'"]
}'The reply (the image is shortened here; this reply was written from the code, not captured from a live run):
{
"created": 1790380421,
"model": "nano-banana-2",
"size": "512x512",
"data": [
{ "b64_json": "iVBORw0KGgoAAAANSUhEUg...", "mime_type": "image/png" }
],
"pack": { "id": "imgpack_9c1f4e0a7d3b58a2c6e41f90", "remaining": 4812, "expiresAt": "2027-04-01T09:00:00.000Z" },
"usage": { "images": 1, "requested_images": 1, "prompt_tokens": 14, "reference_images": 1, "extra_charge_lyd": 0 }
}Request body
data:image/jpeg;base64,..., as a string or as {"data": "...", "mime_type": "image/png"}. PNG, JPEG, WebP, HEIC and HEIF. Links are not downloaded: send the image itself. Up to 4 images of 4 MB each.Default: []1 up to 4. Each one uses one image from your pack and is made on its own.Default: 1512x512 for now (512 also works). Any other size is refused with 400 UNSUPPORTED_SIZE. Larger sizes are priced on request: contact Shafra.Default: "512x512"Editing your own photo and making a new image cost the same. There is no model field: the model is the Nano Banana 2 model, and a model you send is ignored.
Your image pack
Images come from packs you bought once, not from a subscription: 1,000 images, 5,000 images, 10,000 images, 20,000 images, 35,000 images, each as an instant pack or a 24-hour batch pack. Images stay usable for 6 months from the purchase date. When a pack runs out or expires, requests stop with 402 PACK_EMPTY until you buy a new one; the images are never taken from your wallet. This endpoint draws from your instant packs, the one that expires first. Every reply says which pack was used and how many images it has left (the pack object), and the console shows all your packs.
An image is used only when it is delivered. If the image model fails, answers without an image or declines the request, or you disconnect before the answer, the image goes back to the pack and nothing is charged.
Fair use
The pack price includes a prompt of up to 2,000 tokens and one reference image for each image you make. Beyond that, a small amount is charged from your wallet (the balance you also use for the chat API), for each image:
| Extra | Charge for each image made |
|---|---|
| Each extra 1,000 prompt tokens, started (2,001 tokens is one extra, 4,500 tokens is three) | 0.01 LYD |
| Each reference image after the first | 0.01 LYD |
A request needs its extra in your wallet before it starts: if the balance cannot cover it, the request is refused with 402 INSUFFICIENT_BALANCE_EXTRA and nothing is used from your pack. The extra counts toward your company's monthly cap in LYD; the images themselves do not. Prompt tokens are counted by Acacus (an estimate, rounded up to whole thousands for the charge). These numbers can change; the reply's usage.extra_charge_lyd says what was charged.
Limits
| Limit | Value |
|---|---|
| Prompt | 8,000 tokens, about 32,000 characters (the model allows more; Acacus caps it). A longer prompt is refused at once |
| Reference images | 4 images per request, 4 MB each |
| Whole request, photos included | 26 MB |
| Images per request (n) | 4 images |
| Size | 512 x 512 pixels |
| Requests a minute | Your company's limit (the same as your other app keys) |
| Time | A request that Google has not answered in about 2 minutes is given up and not charged |
Repeating a request safely
Send an Idempotency-Key header (up to 128 characters: letters, digits and _ . : -). A request repeated with the same key is one charge. The key is bound to the first request sent with it: a repeat gets the first reply back whatever its body says, so use a new key for a different request.
| When the first request | What the repeat gets |
|---|---|
| finished in the last 15 minutes | The same reply again, with the header Idempotent-Replayed: true. |
| finished more than 15 minutes ago | 409 ALREADY_DELIVERED. Your pack is not charged again, but the images are gone. |
| is still running | 409 REQUEST_IN_PROGRESS with a Retry-After. Ask again after that many seconds. |
| was running when the server stopped | 409 REQUEST_IN_PROGRESS until Acacus frees it, which takes up to 20 minutes. Then the key can be used again. |
| failed (the image went back to your pack) | It is served again. |
The images of a finished reply are kept for 15 minutes so that a retry can return them, and then deleted. Acacus keeps no prompt and no image otherwise, only the counts and the cost.
Errors
Errors come in the same shape as the rest of the API:
{
"error": {
"message": "Your image pack is empty or has expired: 0 images remain. Buy a new pack from Shafra to keep generating. Nothing was charged to your wallet.",
"type": "insufficient_quota",
"code": "PACK_EMPTY",
"param": null,
"remaining": 0
}
}| Status and code | Meaning |
|---|---|
402 PACK_EMPTY | No instant pack has an image left, or the packs have expired. The message says that 0 images remain. Buy a new pack. When some images remain but no single pack can hold what you asked for, the reply says how many. |
402 INSUFFICIENT_BALANCE_EXTRA | The fair-use extra for this request is more than your wallet holds. Top up, or shorten the prompt or send fewer reference images. |
402 CAP_REACHED | Your company's (or this key's) monthly cap in LYD is reached; it counts the extras only. It resets on the first of the month (UTC). |
403 KEY_SCOPE | The key is not an app key of the Image studio product (an ordinary key, or a key for another product), or the company no longer has the product. |
403 BUSINESS_SUSPENDED | The company account is suspended. |
400 INVALID_REQUEST | The body is not a JSON object, the prompt is missing, or n is not a whole number in range. The reply names the field in param. |
400 UNSUPPORTED_SIZE | Only 512x512 is available in packs. |
400 PROMPT_TOO_LONG | The prompt is over 8,000 tokens (or about 32,000 characters, which is checked first). |
400 TOO_MANY_REFERENCE_IMAGES | More than 4 images in reference_images. |
400 INVALID_REFERENCE_IMAGE | A reference image is a link, not base64, not a supported type, or too large. The param is reference_images[i]. |
413 REQUEST_TOO_LARGE | The whole body is too large. Send fewer or smaller reference images. |
409 REQUEST_IN_PROGRESS | The same Idempotency-Key is still running. Retry after the Retry-After seconds. |
409 ALREADY_DELIVERED | The same Idempotency-Key already succeeded and was charged once, more than 15 minutes ago; its images are no longer kept. |
422 IMAGE_BLOCKED | The image model declined the request (its safety rules). Change the prompt or the photo. Nothing was used. |
429 rate_limit_error | Too many requests a minute, or too many at once. Wait Retry-After seconds. |
502 NO_IMAGE_RETURNED, UPSTREAM_ERROR | The image model failed or answered without an image. Try again. Nothing was used. |
503 UPSTREAM_BUSY, STUDIO_DISABLED | The image model is busy (retry after Retry-After), or the studio is switched off for now. |
504 UPSTREAM_TIMEOUT | The image model took too long. Try again. Nothing was used. |
501 BATCH_NOT_READY | From POST /v1/studio/images/batch: 24-hour batch delivery is not available yet. |
More on the format, and which errors to retry, in Errors.
24-hour batch
Batch delivery (images within 24 hours, at the batch pack price) is not built yet. This path answers 501 BATCH_NOT_READY. Use the instant endpoint above with an instant pack. We will announce batch delivery in the changelog when it opens.