Batch edit photos with AI: one edit across many photos
To batch edit photos with AI, send the same edit prompt once per photo, with that photo as the reference. How to script it, pace it, and what it costs.

To batch edit photos with AI, apply the same written edit to each photo as its own request: one photo in, one edited photo out, repeated over the whole folder. With an image-edit API, a batch is a loop in your script that sends each photo as a reference image with the same prompt, then collects the results.
On Sume that loop calls POST /v1/images once per photo. The facts below come from the Image API, Generation admission and Jobs and results docs, read on 2026-09-29. For many new images from a list of prompts, with no photo to edit, see bulk image generation.
How do I batch edit photos with an API?
The Image API's request fields have no list-of-photos option, so each photo is its own request with the same prompt and that one photo in input_references.
| Setting | What to send | Why |
|---|---|---|
| Photo | One input_references entry with a public HTTPS URL | Localhost, private-network, and non-HTTPS reference URLs are rejected before submission |
| Model | One that takes references, such as ChatGPT Image 2.5 (openai/gpt-image-2.5, up to 16) | Models whose input_references descriptor is {"min": 0, "max": 0} are text-to-image only and reject references |
aspect_ratio | "auto" | Matches each result to its own photo; on edit calls, leaving the field out is not the same |
mode | "async" | Returns 202 with a job at once instead of blocking for up to 30 seconds per photo |
Idempotency-Key | One per photo, such as the file name plus an edit version | A retried submit with the same key and body returns the original job |
import os, requests
AUTH = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
PROMPT = ("Brighten this photo and neutralize the white balance. "
"Keep the subject, framing, and every object exactly the same.")
photos = ["https://example.com/shoot/img-001.jpg",
"https://example.com/shoot/img-002.jpg"]
jobs = {}
for url in photos:
body = {
"model": "openai/gpt-image-2.5",
"prompt": PROMPT,
"input_references": [{"type": "image_url", "image_url": {"url": url}}],
"aspect_ratio": "auto",
"mode": "async",
}
name = url.rsplit("/", 1)[-1]
r = requests.post("https://api.sume.com/v1/images", json=body, timeout=30,
headers={**AUTH, "Idempotency-Key": f"brighten-v1-{name}"})
r.raise_for_status()
jobs[url] = r.json()["data"]["job"]["id"]How do I collect the edited photos?
Poll GET /v1/jobs/{id}/status for each job with exponential backoff, and stop on completed, failed, or canceled. Then fetch GET /v1/jobs/{id}/result; results are available only after completion. queued is a normal accepted state, not a failure.
The docs describe /v1/images result URLs as Sume-hosted and signed, so download the edited files you want to keep instead of storing the links. Keep your originals too, and start any second pass from them rather than from an edited copy.
Will every photo get exactly the same edit?
Not guaranteed. An image-edit model draws a new version of each photo, so the same prompt can come out a little differently from one photo to the next, and small details such as text, texture, or faces can drift. The prompt should name the one change and list what must stay; AI photo editing prompts covers that pattern.
Run the prompt on five or ten representative photos first, check them side by side, and only then submit the whole folder. Ask for several versions of one photo with n (up to 10 per call, lower per model) if you want to choose between takes.
How many photos can run at once?
As many as your workspace's generation concurrency limit allows; the rest wait as queued, and a submit fails with 429 queue_full only when the queue is full too. On queue_full, stop adding work and poll existing jobs until at least one finishes. The per-plan numbers are in video job concurrency and queueing, and pacing a script by them is in bulk image generation.
How much does batch photo editing cost?
Each completed image is billed in full at the model's endpoint price, and a failed or cancelled generation is not billed. The per-image price is the pricing line of GET /v1/images/models/{model_id}/endpoints, with Sume's margin already applied, plus a 5.5% agent fee by default. A batch of photos therefore costs the per-image price times the number of photos, times n if you ask for more than one version each. In current code, catalog image prices are the provider's list price × 1.25.
What can't an AI batch edit do?
- No local files: references must be public HTTPS URLs. How to get a public URL for an image covers hosting.
- No pixel-exact edits. The model redraws the photo, so compare results with the originals.
- No documented mask format. ChatGPT Image 2.5 takes an optional
mask_url, but the docs don't describe what the mask image should contain, so name the area in the prompt.
Sources
Related posts
More in Models
- AI outfit change video: change clothes in a clip with AI
Change someone's outfit in an existing video with an AI video-to-video edit: name the garment, what it becomes, and what must stay the same.
- Claude Sonnet 5.5 or Opus 5.5 for an agent that calls a video tool?
Sonnet 5.5 and Opus 5.5 differ in price and release date on Anthropic's pages. Which facts matter when the tool is Sume's video generation, and what stays same?
- How to colorize a black and white video with AI
Colorize a black and white video with an AI video-to-video edit: send the clip and a prompt naming the colors. The model invents them.
- FLUX.2 flex text rendering: prompt tips and the Sume model id
Black Forest Labs positions FLUX.2 [flex] for text and fine detail. How its typography guidance reads, and how to call black-forest-labs/flux.2-flex on Sume.
Written by Sume