"Each input_references entry needs image_url.url": the fix

A bare URL string or a missing url in input_references returns 400 invalid_request on Sume. The exact entry shape, reference ceilings per row, a helper.

5 min readSume
All posts

If Sume's Image API returns 400 invalid_request with "Each input_references entry needs image_url.url.", one of your reference entries is not an object with a nested URL. A bare string such as "https://example.com/a.png" fails, and so does an entry whose image_url has no url. Wrap each reference as {"type": "image_url", "image_url": {"url": "https://..."}} and the call goes through.

The response names the field (input_references), so you know which parameter failed, though not which array index. This post shows the shape, the other things a reference URL must satisfy, and how many references each model takes. The error text was produced by running the request normalizer on origin/main with both bad shapes.

The entry shape that works

The Image API follows an OpenAI-style content-part layout for references. A single edit-style request looks like the example below. The same input_references array is used for plain image-to-image edits, for style references and for multi-image composition; the prompt says what to do with them.

Reference URLs must be public HTTPS. Localhost, private-network and non-HTTPS URLs are rejected before the request is submitted (Sume Image API docs), so a file on your laptop needs to be uploaded somewhere reachable first.

import os, requests

def ref(url: str) -> dict:
    """One input_references entry in the shape Sume expects."""
    if not url.startswith("https://"):
        raise ValueError(f"reference must be public HTTPS: {url}")
    return {"type": "image_url", "image_url": {"url": url}}

body = {
    "model": "openai/gpt-image-2.5",
    "prompt": "Put the mug from the first image on the table in the second image.",
    "input_references": [ref(u) for u in (
        "https://example.com/mug.png", "https://example.com/table.jpg")],
}
r = requests.post("https://api.sume.com/v1/images", timeout=120, json=body,
                  headers={"Authorization": f"Bearer {os.environ['SUME_API_KEY']}"})
print(r.status_code, r.json())

How many references a row takes

The count is a separate limit and is per model. Most edit-capable rows list a ceiling of 10 references; ChatGPT Image 2.5 (Flare and Sunburst) lists 16; Ideogram 4.5 lists 5, where the first image is edited and up to four more act as references. Five rows list none and are text-to-image only, and they reject any reference you send.

Read the input_references range descriptor on GET /v1/images/models rather than hard-coding these numbers, because the catalog is the authority and can change.

input_references ceilings in the Sume image catalog on origin/main (read 2026-10-04)
Row groupMax input_referencesNote
Most edit-capable rows10default ceiling
openai/gpt-image-2.5 (Flare), gpt-image-2.5-sunburst16optional mask_url also accepted
ideogram/ideogram-v4.55first image is edited, up to 4 more are references
Imagen 4 Fast and Ultra, Recraft V4, Qwen Image Max, Higgsfield Soul0text-to-image only

Catch it before you send

The ref() helper above is the cheapest guard: it makes the bad shape impossible to construct and checks the HTTPS rule in the same place. Add a length check against the model's ceiling and you have covered the three reference errors people most often hit.

For the limits across models, see input_references limits by Sume image model. For the cheapest rows that accept a photo, see cheapest Sume image models that take a reference photo.

Related posts

More in Developers

All Developers posts

Written by Sume