> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nozle.dev/llms.txt
> Use this file to discover all available pages before exploring further.

# Installation

> Install and configure the typed, server-side Nozle Go SDK.

The Go SDK requires Go 1.22 or later. Install it with:

```bash theme={null}
go get github.com/nozle-dev/nozle-go@v0.12.0
```

## Create a client

```go theme={null}
import (
import nozle "github.com/nozle-dev/nozle-go"
  "os"
)

client := nozle.New(os.Getenv("NOZLE_SECRET_KEY"))
```

When the key argument is blank or only whitespace, `New` reads the `NOZLE_SECRET_KEY` environment variable. It panics with `nozle: apiKey must not be empty (pass it or set NOZLE_SECRET_KEY)` when both are blank, so check the environment before calling it.

The default Engine and Core URLs are `https://api.nozle.app/engine` and `https://api.nozle.app/core`, both derived from the default host `https://api.nozle.app`. For a local deployment behind one proxy, set the host. `WithBaseURL` and `WithEventsURL` still set one service on its own and win over `WithHost`; if you set only one of them, the other service still uses the host, so set `WithHost` too:

```go theme={null}
client := nozle.New(os.Getenv("NOZLE_SECRET_KEY"), nozle.WithHost("http://localhost:8888"))
```

| Option | Default | Purpose |
| - | - | - |
| API key | `NOZLE_SECRET_KEY` environment variable | Organization credential; protected operations require `sk_`. |
| `WithHost` | `https://api.nozle.app` | Root API origin. Engine calls go to `host/engine` and Core calls to `host/core`. Use it alone for a deployment behind one reverse proxy. |
| `WithBaseURL` | `https://api.nozle.app/engine` | `Track`, `Meter`, `TrackUsage`, `CheckUsage`, `Can`, `TrackCostEvent`, `Ping`, `Plans`, `Checkout`, `CheckoutStatus`, `Subscribe`, `CancelSubscription`, subscription options, previews, transitions and withdrawal, credit balances, Entity get and upsert, and margin. |
| `WithEventsURL` | `https://api.nozle.app/core` | Subscription lookup for `Track`, customer upsert, credit-system list, and Entity subscription calls: ensure, get, list, checkout, bulk checkout (`CheckoutEntitySubscriptions`), and change plan. From `v0.12.0` also invoices, alerts, `CurrentUsage` and `PastUsage`, Nozle's webhook public key for `VerifyWebhook`, and the Feature check of `WrapHTTPClient`. |
| `WithTimeout` | 10 seconds | The budget of each attempt, including any retries inside a custom HTTP client. |
| `WithMaxRetries` | 0 | Extra attempts after a network error, timeout, `429` or `5xx`. 0 never retries. |
| `WithRetryDelay` | 500 milliseconds | First retry delay. It doubles each retry up to 10 seconds, or `Retry-After` is used when sent, capped at 30 seconds. |
| `WithHTTPClient` | default HTTP client | Inject an `*http.Client`, for example one that retries. |
| `WithDebug` | off | Log `[nozle] METHOD url` for each request. |

All methods accept `context.Context`. Reuse one client and keep `sk_` credentials on your server.

## Authentication and transport

`Plans` accepts `pk_` or `sk_`; all other operations require `sk_`. Wrong key types fail locally. A transport failure returns `TransportError`; a non-success HTTP response returns a structured `APIError`. See [Errors and retries](/sdks/go/errors).

By default the SDK makes one HTTP attempt per request. Set `WithMaxRetries(n)` for the SDK's own retries (see [Errors and retries](/sdks/go/errors)), or pass an `*http.Client` whose transport retries. The SDK sets `GetBody` on each request, so the body can be replayed, and the `Idempotency-Key` header is sent again with every attempt:

```go theme={null}
type retryTransport struct{ next http.RoundTripper }

func (t retryTransport) RoundTrip(req *http.Request) (*http.Response, error) {
  for attempt := 0; ; attempt++ {
    resp, err := t.next.RoundTrip(req)
    if attempt == 2 || req.Context().Err() != nil || (err == nil && resp.StatusCode != 429 && resp.StatusCode < 500) {
      return resp, err
    }
    if resp != nil { resp.Body.Close() }
    if req.GetBody != nil {
      body, bodyErr := req.GetBody()
      if bodyErr != nil { return nil, bodyErr }
      req = req.Clone(req.Context())
      req.Body = body
    }
  }
}

client := nozle.New(os.Getenv("NOZLE_SECRET_KEY"), nozle.WithHTTPClient(&http.Client{
  Transport: retryTransport{next: http.DefaultTransport},
}))
```

`WithTimeout` still bounds all attempts together. Retry only after a network error, a 429, or a 5xx, and only operations that carry an idempotency key or a stable transaction ID.

## API surface

| Area | Methods |
| - | - |
| API | `Ping`, `Plans`, `Track`, `Can` |
| Billing | `Checkout`, `Subscribe`, `CancelSubscription`, transition preview/apply, scoped checkout recovery |
| Customers and Entities | `UpsertCustomer`, Entity reads and lifecycle, Entity subscriptions |
| Credits and usage | Credit-system discovery, balances, history, transfers, `CheckUsage`, `TrackUsage` |
| Usage reads | `CurrentUsage`, `PastUsage` |
| Invoices | `ListInvoices`, `GetInvoice`, `InvoiceDownloadURL` |
| Alerts | `ListAlerts`, `GetAlert`, `CreateAlert`, `UpdateAlert`, `DeleteAlert` |
| Webhooks | `VerifyWebhook`, `WebhookHandler` |
| Margin | Summary, customer, metric, plan, model, and trend queries |
| LLMs | Automatic `WrapHTTPClient`, `WrapOpenAIHTTPClient`, `WrapAnthropicHTTPClient`; manual `RecordUsage`, `CaptureOpenAIUsage`, `CaptureAnthropicUsage` |

Usage reads, invoices, alerts, webhooks, `WrapHTTPClient` and `RecordUsage` require `v0.12.0`.

`Ping` returns a `PingResult` with `OK` and `Engine`.

## Next steps

* [Billing and subscriptions](/sdks/go/billing)
* [Customers and Entities](/sdks/go/customers-entities)
* [Product credits](/sdks/go/credits)
* [Tracking events](/sdks/go/tracking-events)
* [Entitlements](/sdks/go/entitlements)
* [Margin queries](/sdks/go/margin-queries)
* [LLM usage capture](/sdks/go/llm-usage)
* [Errors](/sdks/go/errors)

## Choosing credit and provider methods

Use `TrackUsage` for atomic product-credit consumption, and the documented [provider wrappers or manual capture](/sdks/go/llm-usage) for provider telemetry. A separate `Can` plus `Track` is not an atomic reservation; telemetry capture does not provide synchronous provider pricing.

`Consume` and `LLM` were removed in v0.9.1. Their routes did not exist on the hosted service and always returned `404`; use the methods above instead.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.