Go
Generate a context-first Go client for your API using only the standard library.
Typeship generates a context-first Go client for your API using only the standard library. This page covers Go-specific behavior; shared client behavior is on the SDK overview.
CLI and MCP packages are generated and released separately.
Module
- The module path comes from the project's Go destination repository:
github.com/acme/acme-go. Turn on Override module path at the bottom of the Go SDK settings only when the public import address must differ. Until a repository is set, the module path is a placeholder thatgo getcannot resolve. - The package name is read off the module path the way the Go ecosystem reads it.
github.com/stripe/stripe-goispackage stripe. A major-version suffix is ignored. go.modhas norequireblock. The runtime isnet/httpand the standard library.- Every file passes
gofmt -l. Every generation is gated ongo build,go vet, andgofmt.
Idioms
- Context first. Every method takes a
context.Context. Cancel it to abort a request, a paginated iteration, or a stream. (T, error)returns. Methods with no response body returnerroralone.- Params by pointer. Query and header parameters, and the fields of an inline object body, live in one
XxxParamsstruct passed by pointer.nilmeans no parameters. Optional fields are pointers so absent and zero stay distinct;acme.Ptr(v)makes one inline. - Named bodies are arguments. A request body that is a
$refto a named schema, an array, or plain text is a positionalbodyargument with its own type (AccountParams,[]AccountParams,string), so a required body is enforced by the compiler. - Functional options.
acme.New(acme.WithBearerToken(...), acme.WithTimeout(...))for the client,acme.WithRequestTimeout(...)and friends per call. - Iterators.
it := client.Accounts.List(ctx, nil), thenfor it.Next() { it.Value() }andit.Err(). - Initialisms. Identifiers follow Go's convention:
ID,AccountID,URL,HTTPStatus.
Environment variables
New reads these before options apply, so options always win:
| Variable | Sets |
|---|---|
ACME_TOKEN | bearer token |
ACME_API_KEY | the API key, when the spec declares one |
ACME_USERNAME / ACME_PASSWORD | basic auth |
ACME_BASE_URL | base URL |
ACME_WEBHOOK_KEY | webhook key |
The prefix comes from your package name.
Errors
APIError carries Status, Body []byte, RequestID, and Message, plus a Decode(v any) error helper for the body. Per-status types such as *NotFoundError embed APIError, so errors.As matches at either precision. An undocumented status returns a bare *APIError. No response at all returns *TransportError with Method, URL, and a wrapped Err. A cancelled context returns ctx.Err().
Webhooks
client.Webhooks.Unwrap(payload, header) verifies and returns a *WebhookEvent carrying Type and the raw Data. Go has no sum types, so each declared event gets an accessor: event.AsAccountUpdated() returns the typed payload or an error if the type does not match. Events your module has not seen yet still arrive intact. VerifyWebhook and SignWebhook are exported for handlers that do not hold a client.
Streaming
client.Events.Stream(ctx) returns a *Stream. Read it like bufio.Scanner: Next, Event (an SSEEvent), Err, and Close. The stream uses a copy of the HTTP client with no timeout, so cancel through the context.
Uploads
A multipart/form-data field is an acme.Upload{Name, ContentType, Reader} on the params struct: the name and content type the server sees, and an io.Reader for the bytes. The other fields travel alongside as form parts. A raw binary body (application/octet-stream, image/png, ...) is a positional body io.Reader, sent under the spec's content type.
Unions
Go has no sum types. A oneOf/anyOf becomes a named union type that holds the JSON as received and decodes on request: As<Variant>() (Variant, error) and From<Variant>(v) per variant, Raw() for the bytes, and Discriminator() when the spec names one. It is the same shape oapi-codegen generates, and the same accessor pattern the webhook events use. A struct that pretended to be a union would silently drop fields; any would drop the typing.
Response metadata
WithAPIResponse(&meta) on any call fills an APIResponse{StatusCode, Header, RequestID, Body} from the last HTTP response (rate-limit headers, a Location, a request id to quote, or raw bytes for a future field or variant) without going through the global WithOnResponse hook. Go string-backed enum types already preserve unknown server values; generated constants provide autocomplete without closing the wire type.
GraphQL
A GraphQL schema generates one method per query and mutation field on client.Query and client.Mutation. Arguments are the params struct and become variables. Every scalar field to depth 2 is selected by default, with a fragment per concrete type for unions and interfaces, and WithSelection("{ id name }") overrides that per call on methods that return an object. Connection fields return an *Iter[T] like everything else. Errors in a 200 return *GraphQLError (which unwraps to *APIError) carrying the raw Errors.