Go SDK
Coming soonkoo-go is a framework-free, typed Go client for the Koo API. You construct a client with koo.NewClient(baseURL, token) — authenticating with a kc_… API token — and navigate a typed scope chain from account down to a single service. Every method takes a context.Context as its first argument and returns a value or a typed *KooError. It is generated from the same OpenAPI spec as the Node SDK and the API reference, so all three stay in lockstep.
The Go SDK is code-complete and verified in its repository, but the module has not been published to its public import host (github.com/koo-io/koo-go) yet — the go get command below will work once it is. Until then, everything the SDK does is available over plain HTTPS with a kc_… token (see Until then).
go get github.com/koo-io/koo-goRequires Go 1.24 or newer.
Authenticate
The SDK authenticates with a kc_… service-account token — read it from the environment, never hard-code it. Use Whoami to confirm who you're acting as; unlike the browser's /me, it works with a service-account token and tells you the single account the token is confined to.
import ( "context" "os"
koo "github.com/koo-io/koo-go")
client, err := koo.NewClient("https://api.koo.io", os.Getenv("KOO_TOKEN"))if err != nil { return err}
who, err := client.Whoami(context.Background())if err != nil { return err}if who.Kind != koo.WhoamiKindServiceAccount { return fmt.Errorf("use a kc_ service-account token")}accountID := who.ServiceAccount.AccountIDThe scope chain
The client mirrors the API's shape: an account holds projects, a project holds environments, and an environment holds services. Descend with .Account(id).Project(id).Environment(id).Service(name); each hop returns a typed scope value.
account := client.Account(accountID)
project, err := account.Projects().Create(ctx, koo.CreateProjectDto{Name: "web"})env, err := account.Project(project.Id).Environments().Create(ctx, koo.CreateEnvironmentDto{Name: "prod"})Every method takes a trailing ...koo.CallOption (today, koo.WithIdempotencyKey) and returns the decoded body. The full surface:
client.Whoami(ctx) / client.Me(ctx)client.Account(accountID) .Get(ctx) · .Tokens(){ List, Create, Revoke } · .Projects(){ List, Create } .Project(projectID) .Get(ctx) · .Environments(){ List, Create } .Environment(environmentID) .Get(ctx) · .Services(){ List, Create } .Service(name) .Get(ctx) · .Deploy() · .Rollback() · .DeployFromArchive() .Deployments(){ List, BuildLogs } · .Uploads(){ Create } .Logs() · .Metrics()Deploy and watch it roll out
svc := client.Account(accountID).Project(project.Id).Environment(env.Id).Service("api")
dep, err := svc.Deploy(ctx, koo.CreateDeploymentDto{Image: koo.Ptr("ghcr.io/acme/api:sha")})// The deployment status advances through a fixed pipeline:// queued → building → built → applied (image deploys skip the build phases)Poll svc.Deployments().List(ctx, nil) until your deployment's Status is applied — that means the release is on the platform. It is not a health verdict: read svc.Get(ctx) and watch Status.Health reach online (the service is running).
Errors
Every call returns a *KooError on failure, carrying a stable Code, a human Message, optional Details, the HTTP Status, and a RequestID (from the response's X-Request-Id header) to quote to support. Read it with errors.As:
_, err := svc.Deploy(ctx, koo.CreateDeploymentDto{})var kerr *koo.KooErrorif errors.As(err, &kerr) { log.Printf("[%s] %s — reference %s", kerr.Code, kerr.Message, kerr.RequestID)}Retries and idempotency
The SDK retries transient failures for you. Idempotent verbs (GET/HEAD/PUT/DELETE) and any POST carrying an Idempotency-Key are retried on network errors, 429, and 5xx, with full-jitter exponential backoff that honours Retry-After. A 4xx other than 429 — including 401/403 — fails fast on the first request, with no loop.
By default the SDK stamps a stable Idempotency-Key on POSTs so they are safe to retry (the server dedups the write). Pass your own with koo.WithIdempotencyKey(key), or disable auto-stamping with koo.WithAutoIdempotency(false). This is the same policy the Node SDK implements — both are held to a shared conformance vector file.
Until then
The REST API the SDK wraps is already live and documented: the API overview covers authentication, errors, and pagination, and the API reference documents every endpoint. Calling the API from your own code today takes a kc_… API token — so everything the SDK will do is already available over plain HTTPS from Go with net/http, and the CLI drives Koo from your terminal in the meantime.
Related
- API tokens — mint the
kc_…token the SDK authenticates with. - Node SDK — the TypeScript client that defines the shared retry and error conventions.
- CLI — deploy from your terminal with
koo up. - API overview — the conventions the SDK is generated from.