Go: decode a Sume WebP image with golang.org/x/image/webp
Go's image package decodes PNG and JPEG out of the box; WebP needs golang.org/x/image/webp. Decode a Sume image URL and read its size without a re-encode.

Use golang.org/x/image/webp. Its package page shows a decoder only: Decode returns an image.Image, and DecodeConfig returns the colour model and dimensions without decoding the pixels. There is no encoder in that package, so if you need WebP back out, you need another library or you stay in PNG or JPEG.
This matters for Sume because the image API can return WebP. Recraft V4 lists only webp as its output_format, and every other catalog model accepts png, jpeg or webp. If your Go service only imports image/png and image/jpeg, a WebP body fails with an unknown-format error.
What does a complete decode look like?
Fetch data[0].url from a 200 response, then decode the body. The blank import for the format registers the decoder, and the import path of the package is the same one the page documents. Run it with go run main.go <image-url> inside a module that has run go get golang.org/x/image/webp.
DecodeConfig is the cheap call. Use it when you only want to verify that a generated image has the aspect ratio you asked for, and Decode when you need pixels.
package main
import (
"fmt"
"net/http"
"os"
"golang.org/x/image/webp"
)
func main() {
resp, err := http.Get(os.Args[1])
if err != nil {
panic(err)
}
defer resp.Body.Close()
cfg, err := webp.DecodeConfig(resp.Body)
if err != nil {
fmt.Println("not a WebP:", err)
return
}
fmt.Printf("%dx%d\n", cfg.Width, cfg.Height)
}Or skip WebP and ask for PNG
If the service never needs WebP, set output_format to png or jpeg in the request and keep the standard library decoders. Sume checks the parameter against the model's catalog entry, and an unsupported value comes back as 400 unsupported_parameter, not a silent fallback. Read data[].media_type in the response if you want to choose the decoder at run time instead of guessing from the URL.
Status codes before pixels
A Sume image call blocks for up to 30 seconds. A 200 means the body has data[].url. A 202 means the job is still running and the image lives behind the result_url in the job envelope. A 502 means the job failed for good. Check resp.StatusCode first; decoding a JSON error envelope as an image is the most common reason a new integration prints a confusing decode error. The jobs guide covers the polling side.
For cost tracking, the same 200 body has usage.cost, the billed USD amount. Sume bills image models per image, and the token counts in usage are always 0, so decode the cost field and ignore the token fields in a Go struct. Keep one http.Client with a timeout above 30 seconds for the whole service, so a request that Sume holds for the full wait does not die on your own deadline before the 202 arrives.
Sources
Related posts
More in Developers
- Go client for a ported Sora worker: submit, poll, download
A standard-library Go program that submits to Sume POST /v1/videos, polls until the job is terminal, and saves the mp4. Replaces a Go wrapper around Sora.
- Go: poll a Sume job with a context deadline, next_poll_after_seconds
A Go net/http poller for Sume jobs: 20-minute context deadline, sleeps set by next_poll_after_seconds, stops on data.terminal. Standard library only.
- gpt-image-1 cutover calendar: 18 days to Oct 23, 57 to Dec 1
A dated plan for the gpt-image-1 shutdown on 2026-10-23: inventory, canary, cut over and cleanup, with the Dec 1 ids on the same Sume migration.
- GPT Image 2.5 1536x1024 preset vs custom sizes on Sume
1536x1024 is an OpenAI preset and passes Sume's custom-size rules too: edges multiples of 16, max edge 3840, ratio up to 3:1, 655,360-8,294,400 pixels.
Written by Sume