Ideogram is_image_safe in the response: what Sume returns instead
Ideogram's precise edit returns an is_image_safe field per image. Sume has no such field: a refused input ends as a failed job with generation_rejected.

Ideogram's Precise Edit reference (read 2026-10-06) lists is_image_safe among the fields returned for each generated image. Sume's /v1/images response has no equivalent per-image flag. Its documented response is data[].url, media_type and a usage.cost. When the input is refused, you see it on the job.
So the port is not a field rename. You move a check from the image object to the job status.
Where Sume reports a refusal
Sume's errors page lists generation_rejected as a job error category, and the suggested action is to examine the events and correct the unsupported input. Failed jobs carry public error metadata: category, stage, retryability, retry-after seconds, a public reason and a next action. The Image API page adds that failed or cancelled generations are not charged.
Field mapping
| Ideogram signal | Sume signal | What to do |
|---|---|---|
is_image_safe on each image | Job status failed, category generation_rejected | Poll status, then read the error |
| HTTP error on a bad request | 400 with a code such as unsupported_parameter | Fix the request, same idempotency key only if the payload is unchanged |
| Charge when refused | Failed or cancelled: no charge | Check usage.cost on completed jobs only |
A status check that prints the error
This submits a cheap async generation and prints the whole status object, so you can see the category field names for your own account instead of guessing them.
import json, os, time, requests
key = os.environ.get("SUME_API_KEY")
if not key:
raise SystemExit("set SUME_API_KEY")
headers = {"Authorization": f"Bearer {key}", "Idempotency-Key": "safety-probe-001"}
body = {"model": "ideogram/ideogram-v4.5", "quality": "low", "mode": "async",
"prompt": "A plain teal poster that reads OPEN"}
r = requests.post("https://api.sume.com/v1/images", headers=headers, json=body, timeout=60)
data = r.json()["data"]
while True:
s = requests.get(data["status_url"], headers=headers, timeout=30).json()
s = s.get("data", s)
if s.get("terminal"):
print(json.dumps(s, indent=2))
break
time.sleep(2)Handling it in a batch
Batch edits make the difference matter. With a per-image flag you can keep nine good frames and drop one. With a job-level outcome you decide per job, so submit one edit per job and keep your own table that maps each source image to its job id and final status.
Do not resubmit a failed edit unchanged. The refusal is about the input, so a retry spends a request and gets the same answer. Change the source or the instruction, then submit with a new Idempotency-Key.
Sources
Related posts
More in Developers
- Aspect ratios per Sume image model: Banana 2 has 14, Pro 10, GPT 8
Nano Banana 2 lists 14 aspect ratios on Sume, Nano Banana Pro 10 and GPT Image 2.5 8, each plus auto. The full lists, and how to read them from the API.
- image_size beats aspect_ratio on Sume /v1/images: send one, not both
On /v1/images, image_size has priority over aspect_ratio. Use exact pixels for GPT Image 2.5 and an aspect ratio plus resolution tier for Nano Banana.
- Is the Sume Studio Agent an MCP server? No: use mcp.sume.com/mcp
The Studio Agent is not a public MCP connector. Point MCP clients at https://mcp.sume.com/mcp for Sume's tools; use Agent Completions to run the agent.
- Is there a Sume Python SDK? No: use requests and the OpenAPI schema
Sume documents a TypeScript SDK, @sume-com/sdk, and no Python package. From Python, call the REST API with requests, or generate a client from the OpenAPI JSON.
Written by Sume