> For the complete documentation index, see [llms.txt](/llms.txt)

# Go

The Go SDK is an idiomatic, context-aware client emitted from the same `GlottoIR` as every
other target. It ships as a buildable Go module with a `go.mod`, so `go get` then construct a
client and call methods.

## Quickstart

```bash
go get github.com/your-org/petstore
```

`github.com/your-org/petstore` is a placeholder: replace it with the generated module path for
your SDK.

```go
ctx := context.Background()
client := petstore.NewClient(petstore.WithToken(os.Getenv("PETSTORE_TOKEN")))

// a single call
pet, err := client.Pets.CreatePet(ctx, &petstore.NewPet{Name: "Rex"})
if err != nil {
    return err
}

// Pull iteration stops fetching immediately when the loop ends.
for pet, err := range client.Pets.ListPetsIter(ctx) {
    if err != nil {
        return err
    }
    fmt.Println(pet.Name)
}
```

## Context-aware methods

Every method takes a `context.Context` first argument — `client.Pets.CreatePet(ctx, body)` — so
cancellation, deadlines, and request-scoped values flow through the call the idiomatic Go way.

## Pagination

Use the `Iter` companion to range over typed values and errors. It fetches on demand; breaking the
loop releases its work before returning. The original `<-chan Result[T]` methods remain available,
but callers must cancel their context when abandoning a channel. See [Pagination](/docs/pagination).

Manual `Page` companions fetch one typed page at a time. `Response()` decodes the full wrapper without another request, and `NextPage()` retains request options. See [manual pagination](/docs/pagination).

## Retries & backoff

Per-call `RequestOption` values override headers, timeouts, retry counts and idempotency. Methods without an existing option slot expose compatible `WithOptions` companions. See [request options and defaults](/docs/retries).

Transient failures (`5xx`, `429`, transport errors) retry with exponential backoff and jitter;
the policy is configurable per client and honors the request context's deadline. See
[Retries & timeouts](/docs/retries).

## SSE streaming

Server-sent-event endpoints return a typed event stream decoded from the `text/event-stream`
framing. Their `Iter` companions close the response on a range-loop break; NDJSON endpoints use
the same pull API. Establishment shares buffered retry, idempotency and telemetry policy.
`WithRequestTimeout` bounds each opening attempt through the first body byte, then stops.
The context or an explicit `WithStreamTimeout` can bound the established stream. WebSocket
connectors also expose a `WithContext` companion; HTTP 101 ends their opening timeout. See [Streaming](/docs/streaming).

## Webhooks

Use the standalone `VerifyWebhook` helper in your HTTP handler to verify an inbound delivery's
raw body before trusting it. See [Webhooks](/docs/webhooks).

## Polling

Pollable operations receive a `Poll<Method>` companion, and `WaitUntil` covers custom predicates;
both respect context cancellation and deadlines. See [Polling](/docs/polling).

## Telemetry

Pass `WithHooks(&TelemetryHooks{…})` when constructing the client to observe requests, responses,
errors, and retries for your logs, metrics, or traces. See [Telemetry hooks](/docs/telemetry).

## Typed errors

Non-2xx responses return typed error values carrying the parsed error body; use `errors.As`
to narrow to the concrete type rather than matching on status codes. See [Errors](/docs/errors).

## Unknown response fields

Your API can add a response field without it being a breaking change — but a closed Go struct
would drop it, and `encoding/json` discards what it doesn't recognize. The generated models keep
it instead: a field the SDK wasn't generated from is retained on decode, readable through
`ExtraFields()`, and written back out when the model is re-serialized.

```go
pet, _ := client.Pets.CreatePet(ctx, body)

// A field your API started returning after this SDK was generated.
if raw, ok := pet.ExtraFields()["species"]; ok {
    var species string
    _ = json.Unmarshal(raw, &species)
}

// Re-encoding preserves it — a read-modify-write never silently drops it.
body, _ := json.Marshal(pet)
```

`ExtraFields()` returns `map[string]json.RawMessage`, so nested objects and arrays survive intact,
and retention is recursive: a nested model keeps its own unknown fields. A payload whose fields
are all known encodes exactly as before, declared-field order included.

The accessor returns a snapshot: changing its map or `json.RawMessage` bytes does not change the
model or a later request. To send a field your spec does not model yet, use the per-call extra-body
escape hatch.

### Updating retained timestamps

A timestamp the native `time.Time` carrier cannot represent remains available through
`RetainedTemporal()` and survives re-encoding. Assigning a valid `*time.Time` to the typed field
sends your replacement. Use the generated `Set<Field>(value *time.Time)` method to update both
the field and retained state; passing `nil` explicitly sends JSON null, including for an optional
field. For example, a timestamp field named `At` has `SetAt(nil)` unless that method name needs
a collision suffix. The method's generated documentation gives its exact spelling.

A normal struct copy preserves untouched retained values. Calling a timestamp setter on that
copy leaves the original's retained state unchanged. Assigning nil directly leaves the existing
retained wire value available, so use the setter when you intend to clear it.

## Binary downloads

Binary endpoints return an owned `BinaryResponse` with response metadata. `ReadAll(limit)` bounds delivered bytes; `WriteTo` copies to an `io.Writer`. Both close the response. Close it explicitly after abandoning incremental reads. Mixed JSON/binary operations expose an explicit result branch. See [file transfers](/docs/file-transfers).

## File uploads

`multipart/form-data` operations assemble the body with a `mime/multipart.Writer` for you, and an
`application/octet-stream` body is sent raw — so binary uploads work without hand-building the
multipart payload.
