06API basics
Create an image
One request, one image. Describe what to draw, choose a model and an aspect ratio, and collect the result by polling or with a webhook.
This model doesn’t produce every resolution and aspect ratio: the examples use the ones available to it.
Request
/images/ generateSend JSON with the Authorization and Content-Type: application/json headers. Use a new X-Idempotency-Key for every new image, and the previous one when you repeat the same request: that way you will not pay twice (learn more).
# Requires bash, curl, and uuidgen. One idempotency key per request. IDEMPOTENCY_KEY="$(uuidgen)" || exit 1 curl --fail-with-body --max-time 30 \ -X POST https://api.rendergrid.io/ api/ public/ v1/ images/ generate \ -H "Authorization: Bearer $RENDERGRID_API_KEY" \ -H "Content-Type: application/json" \ -H "X-Idempotency-Key: $IDEMPOTENCY_KEY" \ -d '{ "model": "nano-banana-pro", "prompt": "A ceramic mug on marble, soft window light", "resolution": "2K", "aspect_ratio": "16:9" }'
import os import uuid import requests key = os.environ["RENDERGRID_API_KEY"] payload = { "model": "nano-banana-pro", "prompt": "A ceramic mug on marble, soft window light", "resolution": "2K", "aspect_ratio": "16:9", } response = requests.post( "https://api.rendergrid.io/ api/ public/ v1/ images/ generate", headers={ "Authorization": f"Bearer {key}", "X-Idempotency-Key": str(uuid.uuid4()), }, json=payload, timeout=(10, 120), ) response.raise_for_status() creation = response.json() # 202: {id, status, task_id, cost} print(creation["id"])
// Node.js 22+, .mjs file import { randomUUID } from "node:crypto"; const API = "https://api.rendergrid.io/ api/ public/ v1"; const response = await fetch(`${API}/images/generate`, { method: "POST", headers: { Authorization: `Bearer ${process.env.RENDERGRID_API_KEY}`, "Content-Type": "application/json", "X-Idempotency-Key": randomUUID(), }, body: JSON.stringify({ model: "nano-banana-pro", prompt: "A ceramic mug on marble, soft window light", resolution: "2K", aspect_ratio: "16:9", }), signal: AbortSignal.timeout(120_000), }); if (response.status !== 202) { const body = await response.text(); throw new Error(`HTTP ${response.status}: ${body}`); } // a 202 response: {id, status, task_id, cost} const creation = await response.json(); console.log(creation.id);
{
"id": "5b0214ae-9e39-460a-820a-f6ae3e24400b",
"status": "queued",
"task_id": "5b0214ae-9e39-460a-820a-f6ae3e24400b",
"cost": 0.04
}- id
- The task identifier. You use it to get the result: Tasks and statuses.
- status
- Right after acceptance,
queued. - task_id
- The task identifier. In
GET /creations/use{id} id. - cost
- The amount charged for the image, in dollars: a number with four decimal places of precision.
202 Accepted means “request accepted,” not “image ready.”
Build a request
Build the request body and see the price. Each model has its own resolutions and aspect ratios. A grayed-out option cannot be selected: click it to see the response the API would return to refuse it, without charging anything.
42 of 20,000 characters. Delete the text to see how the API declines an empty prompt.
If you omit the resolution, it is 2K.
This model does not support the gray aspect ratios. If you omit the aspect ratio, it is 1:1; auto means the model chooses.
{
"model": "nano-banana-pro",
"prompt": "A ceramic mug on marble, soft window light",
"resolution": "2K",
"aspect_ratio": "16:9"
}The price of this image: $0.04. A failed request is free: the amount goes straight back to your balance.
Request fields
| Field | Type | Description |
|---|---|---|
modelrequired | string | The model identifier from your account’s catalog: Models and parameters. |
promptrequired | string | Describes the image or the edit, up to 20,000 characters. Always required, even when you have reference images. An empty prompt, or one made only of spaces, gets a 400 response, and no money is charged. |
aspect_ratiooptional | string | The aspect ratio, for example 16:9. Without this field it is 1:1—a missing field does not mean auto. Allowed values depend on the model. |
resolutionoptional | string | 1K, 2K, or 4K, case-insensitive. Allowed values and the default depend on the model. |
output_formatoptional | string | The result file format: png or jpg. Omit it to receive the model’s native format. |
image_file_idsoptional | string[] | Up to 14 file_id values from POST /uploads. Do not pass it for text-only generation. For more, see Reference images. |
image_file_idoptional | string | One file_id. A replacement for image_file_ids when there is a single reference image; do not pass both. |
image_urlsoptional | string[] | From 1 to 14 public image URLs. Do not combine with file_id: choose one family of fields. |
webhook_urloptional | string | A public HTTPS URL of up to 2048 characters for the notification that the image is ready: Webhooks. |
The size of the image is set by resolution: it is the model’s size level, not an exact number of pixels. The width and height fields are not accepted. If you need an exact size, look at the dimensions of the file you receive.
One image per request. If you need more, send several requests with different idempotency keys, within your account’s limits.
What is checked before the charge
These checks run before the charge. If the API answered 400 ERR_INVALID_REQUEST, the balance has not changed, and error.details says what to fix.
promptis missing, empty, or made only of spaces.- The chosen model does not have the
resolutionoraspect_ratioyou passed—the list of allowed values arrives indetails.supported. ngreater than 1, orwidthorheight, is passed.- There is a mask (
mask,mask_file_id): masks are not supported. Pass the source image as a reference image and describe the edit in the prompt. - Reference images from two families at once (for example,
image_file_idsandimage_urls), or more than 14 of them. - The
webhook_urladdress is invalid or not allowed.
Price and charge
The price depends on the model and the resolution. For example, Nano Banana Pro costs $0.04 at 1K and $0.07 at 4K, and GPT Image 2 costs $0.02 per image. All prices are on the “Models and parameters” page and in the GET /models response.
The amount is charged when the request is accepted, before work starts, and arrives in the cost field. You can check the balance with a GET /balance request.
A failed request is free: the amount goes straight back to your balance.