Ideogram API image URLs expire: save the edit, and what Sume returns
Ideogram's docs say image URLs expire and to download what you keep. Sume returns a hosted signed URL; here is a download step that works for both.

Yes, they expire, and you should copy the file the moment the edit finishes. Ideogram's API overview (read 2026-10-06) says image URLs expire, so you should download anything you want to keep. The page does not give a time window, so do not build on a guess.
The same rule is cheap insurance on Sume. Its Image API docs say data[].url is Sume-hosted and signed. They do not state a retention window for image results, so treat the URL as a delivery link, not as your archive.
Why it matters for multi-turn edits
Ideogram 4.5 is sold on repeated edits that leave the rest of the image alone. Each pass takes the last result as the next input. If pass three starts from a URL that has lapsed, the chain breaks and you pay again to rebuild passes one and two. Keep your own copy at every step.
What to store per pass
| Field | Ideogram precise edit | Sume /v1/images |
|---|---|---|
| Result location | url in the data array | data[].url, signed, Sume-hosted |
| Output size | Matches the input width and height | An edit with no aspect_ratio keeps the source geometry |
| Expiry | Expires, window not stated | Not stated in the image docs |
| Your copy | Download now | Download now |
| Cost record | Not on this page | usage.cost, the billed USD amount |
Download and check the file
The helper writes the bytes and refuses anything that is not an image, so an error page never lands in your edit chain.
import pathlib, sys, requests
def save(url: str, dest: str) -> str:
r = requests.get(url, timeout=60)
r.raise_for_status()
kind = r.headers.get("content-type", "")
if not kind.startswith("image/"):
raise ValueError(f"not an image: {kind}")
path = pathlib.Path(dest)
path.write_bytes(r.content)
return f"{path} {len(r.content)} bytes {kind}"
if __name__ == "__main__":
if len(sys.argv) != 3:
raise SystemExit("usage: save.py URL DEST")
print(save(sys.argv[1], sys.argv[2]))A simple storage rule
Write each pass to your own storage under a name that carries the pass number, such as hero-v1.png, hero-v2.png. Keep the instruction text next to it. If a later pass goes wrong you can restart from the last good file instead of from the original.
Then give the next call the URL of your copy. Sume's reference inputs must be public HTTPS URLs it can fetch, so a private bucket link without a signature will fail before the model runs.
Sources
Related posts
More in Developers
- 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.
- SSE or WebSocket for AI video progress on Sume? Poll or webhook
Sume has no SSE or WebSocket. mode subscribe is the same 30 s wait as sync. Use async with status polling, the events snapshot, or a webhook. Python example.
- Keep a series voice consistent: pin model, voice, speed and volume
A series sounds the same only if every episode sends the same TTS settings. Keep one profile in code, pin a model id, and send it with each Sume request.
- Same volume every Shorts episode: gain_db, duck_db, one music bed
Sume does not measure loudness. To keep a series consistent, pin audio.gain_db, soundtrack gain_db and duck_db in one function with one bed. Python plan loop.
Written by Sume