502 from the Sume Images API: read code, next_action and status_url

A 502 on POST /v1/images is a failed job, not an outage. Parse error.code, retryable and next_action, then fetch status_url for the job. Python handler.

5 min readSume
All posts

A 502 from POST /v1/images on Sume means the synchronous job reached a terminal failed state inside the wait window; it is the job's verdict, not a gateway outage. Read error.code, error.retryable and error.next_action from the body, then use error.details.status_url to read the job. If retryable is false and next_action is fix_input, change the request, since sending it again will fail the same way.

Branch on the status code first. 200 has the images, 202 is a job that outlived the 30 second sync wait and must be read from the job result URL, and 502 is a failed job. Treating all three as one case is the common bug.

Which fields does the error envelope carry?

From the Sume Image API page (read 2026-10-04):

Error envelope fields on a failed image job, read 2026-10-04
FieldExampleUse
codeinput_media_unreachableStable machine-readable reason
messageCould not download an input media URLShow to a developer, not a customer
retryablefalseDecide whether to retry
next_actionfix_inputWhat to change
details.request_idA job idLog it and quote it to support
details.status_url/v1/jobs/{id}/statusRead the job after failure

What does a handler look like?

The function returns an image URL, a job to poll or raises with the fields you need to log.

import os, requests

def generate(prompt, model="google/nano-banana-2"):
    key = os.environ["SUME_API_KEY"]
    r = requests.post(
        "https://api.sume.com/v1/images",
        headers={"Authorization": f"Bearer {key}"},
        json={"model": model, "prompt": prompt},
        timeout=90,
    )
    if r.status_code == 200:
        return r.json()["data"][0]["url"]
    if r.status_code == 202:
        job = r.json()["data"]
        raise RuntimeError(f"still running: {job['status_url']}")
    err = r.json().get("error", {})
    d = err.get("details", {})
    raise RuntimeError(
        f"{err.get('code')} retryable={err.get('retryable')} "
        f"next={err.get('next_action')} job={d.get('request_id')} "
        f"status={d.get('status_url')}"
    )

if __name__ == "__main__":
    print(generate("A red bicycle against a white wall"))

Will the retry bill me twice?

Sume does not bill failed or cancelled generations, and bills completed ones in full. A 502 is a failure, so a retry is not a double charge for that job. The risk is the opposite case: a timeout on your side after the job actually completed, followed by a second call. Use an idempotency key on retries, as covered in the failed batch retry post.

What do I do with the status URL?

The job still exists after a failure and stays readable at status_url. Fetch it with the same bearer key to confirm the state and log it with the request id. The shared meaning of job states is in the jobs and results docs.

Sources

Related posts

More in Developers

All Developers posts

Written by Sume