Generate a Go client from the Sume OpenAPI with oapi-codegen
The full Sume spec trips oapi-codegen on a [number, null] type, but filtering to the operations you use works. Config, generated names and a short caller.

You can generate a typed Go client from https://api.sume.com/reference/json, but pointing oapi-codegen at the whole document failed in my run today, so list the operations you need with include-operation-ids. With that filter the generator produced a client, and a small caller for the balance route compiled and passed go vet.
The oapi-codegen facts are from its repository page (read 2026-10-10): it supports OpenAPI 3.0 and 3.1, is configured with a YAML file, and generates models and a client with models: true and client: true. What follows is what I observed running v2.8.0 on the spec.
What failed, and what fixed it
The Sume document declares openapi: 3.0.3, yet six properties use the array form of nullable, type: ["number", "null"], which is a 3.1 idiom. In my run the full spec stopped with an error resolving the primitive type for the property generation_spend_cap_usd: unhandled Schema type: &[number null]. The error comes from one request body; the generator does not continue past it.
Filtering fixes it, because only the operations you list are generated. The config below produced a package with Client, NewClientWithResponses and one method per listed operation.
| Route | operationId | Generated method |
|---|---|---|
| GET /v1/me | getAuthenticatedAccount | GetAuthenticatedAccount |
| GET /v1/balance | getApiBalance | GetApiBalance |
| GET /v1/jobs/{id}/status | getApiJobStatus | GetApiJobStatus (takes the id) |
# cfg.yaml
package: sume
output: sume/sume.gen.go
generate:
models: true
client: true
output-options:
include-operation-ids:
- getAuthenticatedAccount
- getApiBalance
- getApiJobStatusCalling it
Run the generator (the caller below assumes a Go module named lane5b with the output in a sume directory), for example go run github.com/oapi-codegen/oapi-codegen/v2/cmd/oapi-codegen@latest -config cfg.yaml openapi.json. Auth is one header per request, so a request editor is the right place for it: send x-api-key or Authorization: Bearer, never both, because the API answers 401 when it sees two.
package main
import (
"context"
"fmt"
"net/http"
"os"
"lane5b/sume"
)
func main() {
key := func(_ context.Context, r *http.Request) error {
r.Header.Set("x-api-key", os.Getenv("SUME_API_KEY"))
return nil
}
c, err := sume.NewClientWithResponses("https://api.sume.com",
sume.WithRequestEditorFn(key))
if err != nil {
panic(err)
}
res, err := c.GetApiBalanceWithResponse(context.Background())
fmt.Println(err, res.StatusCode(), res.JSON200)
}Limits of this approach
The generated structs mirror the document, which is regenerated from the live service; a field the service adds later appears only after you regenerate. Pin the document you generated from in your repo, and diff it when you update. Add operations to the filter one at a time, and expect to hit the nullable-type error again if you add the operation that carries generation_spend_cap_usd.
For polling, keep a hand-written loop around GetApiJobStatus that honors next_poll_after_seconds; the generator gives you types, not behavior.
- Generator version I ran: v2.8.0.
- The full-spec failure may disappear in a later release; check before you rely on the filter.
- Never log the request editor's header value.
Making it repeatable
Treat the generated file as build output. Keep the config with its list of operation ids in the repository, regenerate in one script, and never hand-edit the result, because the next run overwrites it. Commit the file anyway so builds do not need network access to the spec.
When you add an endpoint, add its operation id to the config and regenerate; do not switch to the whole-spec mode until your generator supports the 3.1-style nullable types the spec uses on a handful of properties. Run go vet on the output in CI so a spec change that breaks the generated code fails the pull request instead of a deploy.
- Pin the generator version in
go.modor a tools file. - Send a custom
User-Agentwhen downloading the spec. - Wrap the generated client in one thin type of your own that adds the key header and the idempotency header.
Sources
Related posts
More in Developers
- GitHub Actions concurrency for a Sume render job: the cancel trap
cancel-in-progress stops your workflow, not the Sume job it submitted. Group by branch, cancel via POST /v1/jobs/{id}/cancel in a final step, and cap the run.
- Go 1.27.2 and 1.26.9 patch net/http: update your Sume webhook receiver
Go 1.27.2 and 1.26.9 (2026-10-08) list security fixes in net/http and crypto/tls. A stdlib receiver for Sume webhooks that verifies the signature, in two files.
- Grok Image on Sume: one image per call, so fan out four in Python
x-ai/grok-image lists n as 1 to 1 in the Sume catalog. How to get four variants with four parallel calls, what it costs, and how to stay under queue limits.
- Grok Imagine ignores aspect_ratio on image-to-video; Sume rejects it
xAI says image-to-video output matches the input image and ignores aspect_ratio. Sume's Grok row goes further and rejects the field. Crop the still first.
Written by Sume