Go: net/http client for a 30-second Wan 3.0 clip, 30 lines
A 30-line Go program using only the standard library: submit wan-3.0 for 30 seconds, poll the job, write clip.mp4. Reserve and per-second rate included.

A Go client for a 30-second Wan 3.0 clip fits in 30 lines of standard library: net/http for three calls and encoding/json to read id and status. The program below requests 16:9 at 720p, which Sume reserves at $3.75 ($0.125 per second).
main.go
It passes go vet as written. One call helper sets the bearer token and sends the optional idempotency key; it panics on any status of 300 or above so a failed submit is never read as a job.
package main
import ("encoding/json"; "io"; "net/http"; "os"; "strings"; "time")
func call(method, url, payload, idem string) []byte {
req, _ := http.NewRequest(method, url, strings.NewReader(payload))
req.Header.Set("Authorization", "Bearer "+os.Getenv("SUME_API_KEY"))
req.Header.Set("Content-Type", "application/json")
if idem != "" {
req.Header.Set("Idempotency-Key", idem)
}
res, err := http.DefaultClient.Do(req)
if err != nil || res.StatusCode >= 300 {
panic("request failed")
}
out, _ := io.ReadAll(res.Body)
return out
}
func main() {
const base = "https://api.sume.com/v1/videos"
var job struct{ ID, Status string }
json.Unmarshal(call("POST", base, `{"model":"wan-3.0","prompt":"A drone-style pass over a harbor at dawn",
"duration":30,"resolution":"720p","aspect_ratio":"16:9"}`, "wan-go-001"), &job)
for job.Status == "pending" || job.Status == "in_progress" {
time.Sleep(5 * time.Second)
json.Unmarshal(call("GET", base+"/"+job.ID, "", ""), &job)
}
if job.Status != "completed" { panic("job ended as " + job.Status) }
os.WriteFile("clip.mp4", call("GET", base+"/"+job.ID+"/content?index=0", "", ""), 0o644)
}Design choices
struct{ ID, Status string }matches the JSON keysidandstatusbecause Go's decoder compares field names without regard to case.- Only the POST carries an
Idempotency-Key; if the process dies between submit and poll, rerun with the same key and you get the same job back instead of a second reserve. - The loop ends on any status except
pendingandin_progress, then the program checks forcompleted.
What the same call costs elsewhere in the ladder
Only the resolution string changes the price:
| resolution | 30-second clip | Clips per $20 balance |
|---|---|---|
| 480p | $1.875 | 10 |
| 720p | $3.75 | 5 |
| 1080p | $7.50 | 2 |
Running several at once
Goroutines make it easy to fire ten submits together. Sume's plan limits decide how many jobs are accepted at once, so a burst can meet 429 queue_full while the balance is fine. Cap the number of in-flight submits with a buffered channel, give every clip its own Idempotency-Key, and treat a 429 as a reason to wait and retry the same key.
The balance still has to cover the sum of the holds: ten 720p clips need $37.50 available, and the shortfall check happens per submit.
Next step
Put the call behind a worker that records each job id and its usage.cost once the job completes, and set a client timeout suited to your environment. For a batch, give every clip its own idempotency key and submit in small groups so a 429 only delays the tail.
Sources
Related posts
More in Developers
- gpt-image-2.5 quality auto reserves max: holds from $0.22 to $0.89
On Sume, gpt-image-2.5 with quality auto and auto size reserves $0.8895 per image, while omitting quality reserves $0.2224. Hold table and the safe request.
- Haiku 5.5 prompt caching for a Sume tool list: what breaks the cache
Haiku 5.5 cache hits cost $0.01 per million tokens. Keep the Sume tool list and effort setting stable so a long agent run keeps hitting the cache.
- Haiku 5.5 returns 400 for thinking disabled at xhigh: a Sume agent fix
Claude Haiku 5.5 rejects thinking disabled at xhigh or max effort. How that 400 shows up in an agent that calls Sume, and how to set the pair.
- Hono 4.13.10 split adapters: update a Sume webhook receiver
Hono 4.13.10 moved adapters to @hono/bun, @hono/deno and @hono/cloudflare-workers. The Sume verifyWebhook call needs no change; only the entrypoint imports do.
Written by Sume