07API basics
Reference images
Show the model your own image and say what to do with it: keep the product, change the background, continue the style. You can upload a reference image as a file or pass it as a link.
This model doesn’t produce every resolution and aspect ratio: the examples use the ones available to it.
How to pass reference images
Reference images are optional: without them the model draws from the text alone. If you need them, choose one family of fields: a file you uploaded in advance, or an image address.
| Method | Request field | When to choose it |
|---|---|---|
| No reference images | do not pass any | The image is made from scratch, from the prompt |
| An uploaded file | image_file_ids (up to 14) or image_file_id | The file is on your disk; one reference image is needed in several requests |
| An image address | image_urls (up to 14) | The image is already available at a public link |
{
"model": "nano-banana-pro",
"prompt": "Keep the lamp, put it on a light windowsill",
"resolution": "2K",
"image_file_ids": ["ea7b3c89972d3657"]
}{
"model": "nano-banana-pro",
"prompt": "Keep the lamp, put it on a light windowsill",
"resolution": "2K",
"image_urls": ["https:// cdn.example.com/ products/ lamp.png"]
}Do not mix the methods. If one request has both image_urls and file_id, the API answers 400 ERR_INVALID_REQUEST before the charge. The fields image, image_url, image_input, and input_urls are not accepted.
Uploading a file
/uploadsSend the file as multipart/form-data: the file field is the file itself, and the kind field has the value image. The response contains a file_id: put it in the generation request.
curl --fail-with-body --connect-timeout 10 --max-time 120 \ -X POST https://api.rendergrid.io/ api/ public/ v1/ uploads \ -H "Authorization: Bearer $RENDERGRID_API_KEY" \ -F "file=@lamp.png;type=image/png" \ -F "kind=image"
import os import requests key = os.environ["RENDERGRID_API_KEY"] with open("lamp.png", "rb") as image: response = requests.post( "https://api.rendergrid.io/ api/ public/ v1/ uploads", headers={"Authorization": f"Bearer {key}"}, files={"file": ("lamp.png", image, "image/png")}, data={"kind": "image"}, timeout=(10, 120), ) response.raise_for_status() upload = response.json() print(upload["file_id"], upload["expires_at"])
// Node.js 22+, .mjs file import { readFile } from "node:fs/promises"; const bytes = await readFile("lamp.png"); const file = new Blob([bytes], { type: "image/png" }); const form = new FormData(); form.append("file", file, "lamp.png"); form.append("kind", "image"); const API = "https://api.rendergrid.io/ api/ public/ v1"; const key = process.env.RENDERGRID_API_KEY; const response = await fetch(`${API}/uploads`, { method: "POST", headers: { Authorization: `Bearer ${key}` }, body: form, signal: AbortSignal.timeout(120_000), }); if (!response.ok) { const body = await response.text(); throw new Error(`HTTP ${response.status}: ${body}`); } const upload = await response.json(); console.log(upload.file_id, upload.expires_at);
{
"file_id": "ea7b3c89972d3657",
"url": "https:// cdn.rendergrid.io/ user_uploads/ example.png",
"expires_at": "2026-10-14T12:00:00+00:00"
}- file_id
- The file identifier. It belongs to the account that uploaded it.
- url
- The address of a copy of the file. This is not permanent storage: after
expires_atyou cannot use it. - expires_at
- When
file_idstops working: 24 hours after the upload.
| Item | Rule |
|---|---|
| Formats | PNG, JPEG, and WebP. GIF and BMP are not accepted |
| Size | up to 25 MiB (26,214,400 bytes) per file |
| Lifetime | file_id lives for 24 hours. Using it in a request does not extend that time |
| Re-upload | The same file uploaded again gets a new file_id for another 24 hours |
| Money | Nothing is charged to the balance for an upload |
| Daily limit | An account that signed up on its own and has not topped up yet uses no more than 100 reference images per day, by UTC: uploaded files and addresses in image_urls are counted together. After the first top-up there is no limit |
Check the file before sending
This is how the API responds to the most common files. All of these refusals arrive immediately, before generation.
An address instead of a file
If the image is already online, do not upload it: pass the link in image_urls. Our server downloads the image, so the link must open from outside without signing in.
- A public
http://orhttps://address on port 80 or 443. Addresses on internal networks and links with a username and password inside do not work. - Redirects are not followed: give the final address of the image.
- The response must be a PNG, JPEG, or WebP image of no more than 25 MiB.
- The source must respond quickly: the download time is limited. If the source is slow or password-protected, download the file yourself and upload it through
POST /uploads.
How to prepare reference images
- Say in the
promptwhat to keep and what to change. The model sees the reference image but does not know what you want from it. - Up to 14 reference images per request.
- A reference image heavier than 7 MiB or longer than 4,096 pixels on its long side may be downscaled or recompressed before processing. For large images with a transparent background, the background may become white.
- Keep the originals yourself:
file_idis valid for 24 hours after the upload, and the file itself is deleted 48 hours after the last upload. - Masks (inpainting) are not supported. Pass the source image as a reference image and describe the edit in words.
What can go wrong
These refusals arrive before the charge: the balance does not change.
| What happened | API response | What to do |
|---|---|---|
| The file is larger than 25 MiB | 400 ERR_INVALID_REQUEST, “File exceeds the maximum allowed size”, details.max_bytes | Compress the file or reduce the image |
| GIF, BMP, or another format | 400 ERR_INVALID_REQUEST, “Unsupported image format. Supported formats: PNG, JPEG, WebP.” | Save the image as PNG, JPEG, or WebP |
| The file is empty or is not an image | 400 ERR_INVALID_REQUEST, “Uploaded file is empty” or “File content does not match the declared media kind” | Check the file: a .png extension does not make it an image |
file_id expired or is unavailable | 400 ERR_INVALID_REQUEST, details.reason: reference_unavailable, details.input_index, details.retryable: false | Upload the file again and use the new file_id |
| The link could not be downloaded | 422 ERR_INPUT_FETCH_FAILED, details.retryable, details.input_index | Retry only if retryable: true. Otherwise fix the link or upload the file yourself |
| More than 14 reference images, or two methods at once | 400 ERR_INVALID_REQUEST, details.errors | Keep up to 14 reference images and one family of fields |
| The request has a mask | 400 ERR_INVALID_REQUEST, details.fields: ["mask_file_id"] | Remove the mask, pass the source image as a reference image, and describe the edit in words |
| The daily upload limit is used up | 429 ERR_RATE_LIMIT, “Daily upload limit reached. Add funds to your account to lift it.”, details.limit, details.window = "1d", details.retry_after, and the Retry-After header | Top up your balance—the limit is lifted—or wait for the next day in UTC |
If a reference image becomes unavailable after the request is accepted, the task ends with the status failed and failure.code: reference_unavailable or reference_fetch_failed. For more, see “Error codes.”
A failed request is free: the amount goes straight back to your balance.
Frequently asked questions
How many reference images can I pass?
image_file_ids and image_urls take from 1 to 14 values.Can I use one file_id in several requests?
file_id.Do you accept GIF?
image_urls.Why does a reference image upload answer 429?
image_urls. Top up your balance and the limit goes away; otherwise wait for the next day. For more, see “Limits.”