Image editing is one of the more demanding parts of an AI product surface: a user uploads a photo, describes a change, and expects a result. Edits that use several source images, a large canvas, or a heavier prompt take longer than a typical synchronous HTTP call comfortably allows. This guide covers the correct TokenLab endpoint, the two supported image input forms, multi-image edits, and the async path for slow requests.
The endpoint
Image editing lives at POST /v1/images/edits — note the plural edits. (A common mistake is writing /images/edit, which is not the documented path.)
The endpoint supports two request shapes:
- An OpenAI-compatible
multipart/form-dataupload flow. - A JSON request that supplies
image_url,image_urls, or officialimages[]references for supported image-to-image families.
The full request and response fields are documented in the Edit Image API reference.
What gpt-image-2 accepts here
- Multipart
imageuploads. - JSON
image_urlorimage_urls. - Official
images[]references, where each object contains exactly one ofimage_urlorfile_id. - Up to 16 source images per request.
A few constraints worth knowing before you write code:
gpt-image-2edits do not acceptresolution; usesizefor output dimensions (eitherautoorWIDTHxHEIGHT, with dimensions in multiples of 16, longest edge at most 3840px, long/short ratio at most 3:1).backgroundacceptsautooropaque;transparentis not supported.input_fidelityis not part of the supported fields forgpt-image-2; sending it returns400 unsupported_parameter.- For JSON requests, provide exactly one of
image_url,image_urls, orimages. Eachimages[]object must contain exactly one ofimage_urlorfile_id. Values forfile_idmust be created through/v1/filesfirst. - Nano Banana reference-image requests belong on
/v1/images/generationswithoperation: "image-to-image"andimage_urls— not on/v1/images/edits.
Multipart uploads vs JSON image references
Both work for gpt-image-2. Pick the one that matches where your image bytes already are.
Multipart — use this when the application holds the file, whether from a user upload or a generated asset. Repeat the image field to send multiple sources. Files must be PNG, JPEG, or WebP, at most 50 MiB each.
curl -X POST "https://api.tokenlab.sh/v1/images/edits" \
-H "Authorization: Bearer sk-your-api-key" \
-F "model=gpt-image-2" \
-F "image=@subject.png" \
-F "image=@background.png" \
-F "prompt=Combine the subject with the new background." \
-F "size=1024x1024"
JSON image URLs — use this when the images already live at a public URL, or you generated them in an earlier TokenLab request and already have a URL.
curl -X POST "https://api.tokenlab.sh/v1/images/edits" \
-H "Authorization: Bearer sk-your-api-key" \
-H "Content-Type: application/json" \
-d '{
"model": "gpt-image-2",
"images": [
{"image_url": "https://example.com/subject.png"},
{"image_url": "https://example.com/background.png"}
],
"prompt": "Combine the subject with the new background.",
"size": "1024x1024",
"async": true
}'
Remote URLs must be public http/https, without embedded credentials or fragments, and must not resolve to localhost, private, or reserved IP ranges. TokenLab fetches the bytes and hands them to the model as multipart image parts. Per-image limit is 50 MiB; the aggregate limit for URL-fetched images in one request is 200 MiB; fetch timeout is 30 seconds; up to 3 redirects are followed.
Multi-image edits and async polling
Multi-image edits are the clearest case for async: true. Sending several images with a complex instruction set through a synchronous call means holding a connection open for however long the model needs. Set async: true on gpt-image-2 (and on official FLUX/BFL edit models) to receive a task instead:
{
"created": 1706000000,
"id": "ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"task_id": "ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"status": "pending",
"poll_url": "/v1/tasks/ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"data": []
}
Poll the returned poll_url, or fall back to GET /v1/tasks/{task_id}. Statuses are pending, processing, completed, and failed. A completed image task returns data[].url. Checking every 3–5 seconds is enough; stop on a terminal status rather than continuing to poll.
curl "https://api.tokenlab.sh/v1/tasks/ldtask_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" \
-H "Authorization: Bearer sk-your-api-key"
Async edit tasks return final image URLs regardless of the requested response_format. If you need raw b64_json, use a synchronous request.
Billing may reserve the estimated amount when the task is created; a completed task is billed by actual usage, and a failed or timed-out task releases or refunds the reservation. See Async jobs and polling for the full lifecycle, and Get Image Status for the response fields.
When to use each mode
Use async: true when:
- You are sending multiple source images in one request.
- Your prompt or instruction set is complex enough that generation time is unpredictable.
- You run edits in a background job, queue, or batch process rather than a live user-facing request.
Stay synchronous when:
- You are doing a single-image edit with a short prompt.
- Your client prefers to fail fast rather than poll.
For synchronous calls, set your HTTP client timeout to at least 120s; high-resolution or high-quality requests can take close to a minute or longer. If the create response still comes back with status: "pending", task_id, or poll_url, switch to the returned polling flow.
Input errors to expect
Remote image fetch failures are returned as input errors before generation begins. Unreachable URLs, timeouts, 403/404 responses, private or internal hosts, credentials or fragments in the URL, non-image content, unsupported formats, and size-limit violations return 400 or 413 and identify the offending image_url or image_urls[n]. For private or header-protected assets, upload multipart image files directly, or create /v1/files references and pass them as images[].file_id.
xAI Grok Imagine image edit models (for example grok-imagine-image and grok-imagine-image-quality) use the same input fields but cap source images at 3; more than that returns 400 too_many_images.
Integration checklist
- Target
POST /v1/images/editsand send themodelexplicitly. - Choose multipart uploads or JSON references based on where your images already live.
- Send exactly one of
image_url,image_urls, orimages[]in JSON requests; eachimages[]entry has exactly one ofimage_urlorfile_id. - Use
async: truefor multi-image or heavy edits; poll the returnedpoll_urluntil the task reachescompletedorfailed. - Set client timeouts to at least 120 seconds for synchronous requests and handle a
pendingresponse by followingpoll_url. - On a client timeout, check whether a task was created before retrying the create request to avoid duplicate charges.
Get started
Query GET /v1/models?recommended_for=image to see current image models, then open a model's detail page to confirm its supported operations and request fields before sending a request. Create an API key from the console to test the edit endpoint with your own images.
Sources
- https://docs.tokenlab.sh/api-reference/images/edit-imageSources checked 2026-09-27
- https://docs.tokenlab.sh/guides/async-jobs-pollingSources checked 2026-09-27
- https://docs.tokenlab.sh/api-reference/images/get-image-statusSources checked 2026-09-27



