Sume video jobs in Go: net/http, a struct, and a poll loop
A Go program that submits a Sume video job with net/http, decodes the job into a struct, polls to completed, and prints the URL and cost in 30 lines.

Go's standard library is enough for Sume's asynchronous video API. The program below posts a sume/auto job, decodes the job body into a small struct, polls every 20 seconds, and prints the first download URL plus usage.cost once the job is completed.
The code
Set SUME_API_KEY. The program submits one job, polls polling_url every 20 seconds until completed, and prints the first download URL.
package main
import ("encoding/json"; "fmt"; "net/http"; "os"; "strings"; "time")
type Job struct {
Status string
PollingURL string `json:"polling_url"`
UnsignedURLs []string `json:"unsigned_urls"`
Usage struct{ Cost float64 }
}
func call(method, url, body string) Job {
req, _ := http.NewRequest(method, url, strings.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("SUME_API_KEY"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil { panic(err) }
defer res.Body.Close()
var j Job
json.NewDecoder(res.Body).Decode(&j)
return j
}
func main() {
job := call("POST", "https://api.sume.com/v1/videos",
`{"model":"sume/auto","prompt":"A tram crossing a bridge at dawn","aspect_ratio":"16:9"}`)
for {
time.Sleep(20 * time.Second)
s := call("GET", job.PollingURL, "")
fmt.Println(s.Status)
if s.Status == "completed" { fmt.Println(s.UnsignedURLs[0], s.Usage.Cost); return }
if s.Status == "failed" || s.Status == "cancelled" { os.Exit(1) }
}
}What to know
sume/auto currently resolves to Gemini Omni Flash 1.1 and takes 3 to 10 seconds in 16:9 or 9:16. The defaults are 720p and 8 seconds, so this call bills $1.00 (list $0.10 per second x 1.25 x 8 s). A failed or cancelled job ends the loop with a non-success status; check error in the poll body.
usage.cost is a JSON number in the documented response, so float64 decodes it. The program was vetted with go vet but not run against the live API. For a service, wrap the loop in a context with a deadline and switch the sleep to time.Ticker; a clip on a slower model can take several minutes.
Sources
Related posts
More in Developers
- Sume video mode: async, sync, subscribe or webhook? Cost is the same
Mode only decides how you learn the outcome: all four create the same job at the same price. A decision table for web apps, workers and batch pipelines.
- Which Sume video model is fastest? The catalog's latency labels
Each Sume video model card carries a typical-latency label. Which rows are fast, medium or medium-slow, and what you pay for the faster ones.
- Sume webhooks: 10 attempts 30 seconds apart for a video receiver
A Sume job webhook is tried up to 10 times, 30 seconds apart by default, with a 10 s timeout each. What that means for a video receiver, plus a Python verifier.
- Sume webhook.test has no job_id: keep it out of your job table
The dashboard's Send test posts a signed webhook.test with no job_id. Route on event first, dedupe on job_id second, and no phantom job row appears.
Written by Sume