Change the price on an ad banner for each market: an edit loop

One banner, three markets: a Python loop that sends one edit per price with an Idempotency-Key, so a retry never pays for the same banner twice.

5 min readSume
All posts

To change one number on an ad banner for several markets, send one edit call per market: the original banner as a reference, a prompt that names the exact old and new text, and aspect_ratio: "auto" so the output keeps the banner's shape. Give each call its own Idempotency-Key, so a retry after a timeout reuses the same job.

Text replacement that keeps layout is the headline feature of Ideogram 4.5 on Higgsfield, listed 2026-09-30 (Higgsfield changelog, read 2026-10-02). On Sume the same task runs on a listed model: ChatGPT Image 2.5 takes up to 16 references.

What does one edit call look like?

The reference goes in input_references as a public HTTPS URL. On edit calls Sume's docs say to prefer aspect_ratio: "auto" to match the reference, and note that omitting the field is not the same as auto.

The loop below sends three markets. mode: "async" returns a job envelope, so a slow edit never blocks the loop.

import os
import requests

URL = "https://api.sume.com/v1/images"
HEADERS = {"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"}
BANNER = "https://example.com/banner-us.png"
PRICES = {"us": "$49", "uk": "GBP 39", "de": "EUR 45"}

for market, price in PRICES.items():
    body = {
        "model": "openai/gpt-image-2.5",
        "prompt": f"Replace the price text '$49' with '{price}'. "
                  "Change nothing else: same layout, fonts, colours.",
        "input_references": [{"type": "image_url",
                              "image_url": {"url": BANNER}}],
        "aspect_ratio": "auto",
        "mode": "async",
    }
    headers = {**HEADERS, "Idempotency-Key": f"banner-v3-{market}"}
    r = requests.post(URL, headers=headers, json=body, timeout=60)
    print(market, r.status_code, r.json().get("status_url"))

Why one call per market?

Each market is a separate paid job with its own result, so one failure does not take the others down. Sume bills image generation all-or-nothing: a completed generation is billed in full, and a failed or cancelled one is not billed.

Reuse an idempotency key only for an exact retry; the docs say to reuse a key only for the same operation and payload, so a changed price gets a new key.

Behaviour from Sume's docs, read 2026-10-02
SituationWhat Sume does
Same key, same payloadExact retry of the same operation
Same key, different payloadNot a retry; use a new key
Failed generationNot billed
Completed generationBilled in full

How do I check the result?

Read each job's result for data[].url or result.artifacts[], then check the dimensions and the text by eye. A model can still drift on a small number, so a human glance per market is the cheap safeguard; the QA check post covers the dimension test.

Sources

Related posts

More in Use cases

All Use cases posts

Written by Sume