Generate 100 images with the Sume Image API: async jobs and polling
Submit each image with mode async, collect job ids, then poll status. Each job bills only if it completes; failed jobs use no credits.

Use mode: "async" for each request, keep the job ids, and poll GET /v1/jobs/{id}/status until terminal is true. For a run of 100 images on qwen/qwen-image at $0.025 billed each, the total is $2.50 if all jobs complete. A job that fails or is cancelled uses no credits, per the Image API docs.
Plan the run
n is capped at 4 per call on most rows and at 1 on x-ai/grok-image, so 100 images can be 25 calls of n: 4 or 100 calls of n: 1. One call is one job, so batching with n reduces your job count. The arithmetic below uses the list x 1.25 formula, with each job rounded up to the cent; the Grok row is the only one where that matters, since a single 2.5 cent image bills as 3 cents.
| Row | Billed per image | 100 images | Calls at max n |
|---|---|---|---|
| qwen/qwen-image | $0.025 | $2.50 | 25 |
| x-ai/grok-image | $0.025 list x 1.25; $0.03 per n=1 job | $3.00 | 100 |
| black-forest-labs/flux.2-pro | $0.0375 | $3.75 | 25 |
| google/nano-banana-2.1 (1K) | $0.10 | $10.00 | 25 |
Submit and poll
The script submits all jobs first and then polls them in a loop. It prints the final sume_status for each. Fetch result_url for completed jobs to read the image URLs. Add an Idempotency-Key header per job if your runner can retry the submit step.
import os, time, requests
H = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
jobs = []
for i in range(25):
r = requests.post(
"https://api.sume.com/v1/images",
headers=H,
json={"model": "qwen/qwen-image", "prompt": f"flat icon set {i}", "n": 4, "mode": "async"},
timeout=30,
)
r.raise_for_status()
body = r.json()
jobs.append(body.get("data", body)["status_url"])
for url in jobs:
while True:
s = requests.get(url, headers=H, timeout=30).json()
s = s.get("data", s)
if s.get("terminal"):
print(url, s.get("sume_status"))
break
time.sleep(s.get("next_poll_after_seconds") or 3)Before a big run
- Run 3 jobs first and read the result shape.
- Check your plan's concurrency before you fire 25 at once.
- Cap the polling loop with your own deadline; a client timeout does not cancel the job.
Sources
Related posts
More in Developers
- Generate Grok Imagine clips from an agent with the generate_video tool
Hosted MCP exposes generate_video, which replaced video-router_create. How an agent should call it for grok-imagine-video-1.5 and what to read first.
- Can the Sume Image API output SVG? Not today; formats you get
No: output_format svg is in the schema for parity, but no catalog model advertises it, so the request is rejected. Sume returns png, jpeg or webp.
- GET /v1/balance returns available_credits: a TypeScript gate
Sume's balance read returns whole credits in available_credits, a funded or empty state, and expiring_soon_credits. Gate a job on it in TypeScript.
- Go 1.27.2 synctest: test a 30-second Sume poll loop in milliseconds
Test a Go poll loop for Sume video jobs with testing/synctest: 90 seconds of fake sleeps and a 20-minute deadline pass in under a second, no sockets.
Written by Sume