Go net/http client for Sume images: handle 200 and 202 on a model swap
A Go program that posts to Sume /v1/images with the model id from an env var and branches on 200 versus 202, so a gpt-image-1 swap is not a rebuild.

In Go, read the model id from an environment variable, post to https://api.sume.com/v1/images, and branch on the HTTP status: 200 carries an image list in data, and 202 carries a job envelope with status_url. The same binary then runs against any Sume image id, so a swap from a retired gpt-image-1 call is a changed variable, not a rebuild.
The two bodies share the key data but not its type: a list on 200 and an object on 202. Decode into the shape that matches the status code.
The client
Set an explicit client timeout above Sume's 30 second default wait. http.DefaultClient has no timeout.
package main
import ("bytes"; "encoding/json"; "fmt"; "net/http"; "os"; "time")
func main() {
body, _ := json.Marshal(map[string]any{"model": os.Getenv("SUME_IMAGE_MODEL"), "prompt": "ceramic mug on linen"})
req, _ := http.NewRequest("POST", "https://api.sume.com/v1/images", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("SUME_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := (&http.Client{Timeout: 60 * time.Second}).Do(req)
if err != nil {
panic(err)
}
defer res.Body.Close()
switch res.StatusCode {
case 200:
var ok struct{ Data []struct{ URL string `json:"url"` } `json:"data"` }
json.NewDecoder(res.Body).Decode(&ok)
fmt.Println(ok.Data[0].URL)
case 202:
var job struct{ Data struct{ StatusURL string `json:"status_url"` } `json:"data"` }
json.NewDecoder(res.Body).Decode(&job)
fmt.Println("poll", job.Data.StatusURL)
default:
fmt.Println("failed", res.StatusCode)
}
}What each status means
| Status | Body | Action |
|---|---|---|
| 200 | data is a list of {url, media_type}; usage.cost is billed USD | Download or store the URL |
| 202 | data.job.id, status_url, result_url | Poll GET /v1/jobs/{id}/status, then result |
| 404 | model_not_found | Fix the id in SUME_IMAGE_MODEL |
| 400 | unsupported_parameter | Remove the field the model does not list |
Run it
Run SUME_IMAGE_MODEL=openai/gpt-image-2.5-sunburst go run main.go. Slow settings such as 4K and high quality can degrade to a 202, so keep the 202 branch even if your test prompt returns a 200. The id and date details are in the main shutdown post.
Sources
Related posts
More in Developers
- gpt-image-1 returns 404 model_not_found on Sume: which id to send
gpt-image-1, gpt-image-1.5 or gemini-2.5-flash-image sent to Sume /v1/images return 404 model_not_found. Ids to send instead, plus a lookup.
- Heroku H12 at 30 seconds: call Sume async, not sync
Heroku's router ends a request at 30 s (H12). Sume sync mode waits up to 30 s too. Submit async, return 202 to the browser, then poll or take a webhook.
- How Sume TTS splits a script into sentence ids (. ! ? only)
Sume's script source cuts sentences at periods, exclamation and question marks only, keeps every character, and numbers them sent_000000. Examples and traps.
- Huey task that polls an AI video job with schedule(delay=...)
A Huey task reads Sume's job status once and reschedules itself with task.schedule(delay=...) from next_poll_after_seconds, so no worker thread sleeps.
Written by Sume