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

# Go SDK

> github.com/itemshop/sdk-go — storefront and the API client for Go 1.23+, no dependencies.

`github.com/itemshop/sdk-go` — no dependencies (just `net/http`), Go ≥ 1.23 (`iter.Seq2` iterators). Every method takes a `context.Context` and returns `(result, error)`.

| Package | What for | Secrets |
| - | - | - |
| `storefront` — `storefront.New(shopIDOrDomain)` | Storefront API v1: shop, products, payments, discounts, checkout, order status, widgets | **none** |
| `itemshop` — `itemshop.NewClient(apiKey)` | the full keyed API + Sites API (`client.Site`) | API key (`X-API-Key`) |

## Installation

```bash theme={null}
go get github.com/itemshop/sdk-go
```

## Storefront (no key)

```go theme={null}
sf := storefront.New("664f1a2b3c4d5e6f7a8b9c0d", storefront.WithLocale("pl"))
// or the shop's uniqueName / domain: storefront.New("sklep.example.com")

list, err := sf.Products.List(ctx, &storefront.ProductsListParams{Category: serverID})
// list.Products, list.Categories (category = the shop's server)
methods, err := sf.PaymentMethods.List(ctx)

res, err := sf.Checkout.Create(ctx, storefront.CheckoutInput{
	Items:             []storefront.CartItem{storefront.Item(list.Products[0].ID, 1)},
	Nick:              "Steve",               // game shops; general shops use Email
	Email:             "steve@example.com",
	AcceptTerms:       true,
	ImmediateDelivery: true,
	PaymentMethodCode: methods[0].Code,
	PaymentChannel:    "blik",                // methods[i].Channel
	ReturnURL:         "https://sklep.example.com/dziekujemy",
})
// redirect the buyer to res.RedirectURL; after the gateway:
returned, ok := storefront.ReturnedOrderFromReturnURL(returnedURL) // ?itemshop_order=<number>&itemshop_key=<key>
if ok {
	status, err := sf.Orders.WaitPaidByNumber(ctx, returned.Number, returned.Key, 0)
	// or sf.Orders.StatusByNumber(ctx, res.OrderNumber, res.StatusKey) right after checkout
}

redemption, err := sf.Vouchers.Redeem(ctx, "KOD123", "Steve", turnstileToken)
```

* `Checkout.Create` fills in `consents.legalVersion` from `Shop.Legal.Version` and always sends an `Idempotency-Key` (generated or `input.IdempotencyKey`), so a retry after a dropped connection never creates a second order. The Turnstile token is optional.
* A cart has 1–20 lines (`Items`); two or more form one payment group (`GroupID`, `OrderIDs` in the result), more than 20 → `CART_TOO_LARGE`. The old `OrderIDFromReturnURL` / `Orders.Status` serve pre-3.0 orders only.
* `Vouchers.Redeem` is not retried (except on 429).
* Widgets: `sf.Widgets.RecentPurchases`, `TopSpenders`, `MonthlyGoal`, `OnlinePlayers` — switched off by the owner they return empty results, not an error.
* `nullable` fields in response types are pointers.

## API client (with a key)

```go theme={null}
client := itemshop.NewClient(os.Getenv("ITEMSHOP_API_KEY")) // empty key → $ITEMSHOP_API_KEY

product, err := client.Products.Create(ctx, shopID, api.CreateProductDto{
	Name: "VIP", Price: 19.99, ServerID: serverID,
	Commands: []string{"lp user {PLAYER} parent set vip"},
	IsActive: itemshop.Bool(true),
})

// pagination: an iterator over all pages, fetched lazily
for order, err := range client.Orders.All(ctx, shopID, &itemshop.OrdersListParams{Status: "paid"}) {
	if err != nil {
		return err
	}
	fmt.Println(*order.OrderNumber)
}

// site as code — the equivalent of `itemshop deploy`
dep, err := client.Site.Deploy(ctx, shopID, zipFile, itemshop.DeploymentProduction)

// AI Workspace
setup, err := client.Workspace.AgentSetup(ctx, shopID, "claude-code") // ready MCP config file
```

Services: `Shops, Servers, Products, PaymentMethods, PaymentErrors, Blacklist, Discounts, Vouchers, Stats, Uploads, Orders` plus the hand-written `Site`, `Templates`, `Workspace`, `Agents`, `Skills`. Workspace tokens need a panel session — with an API key you get 401/403. For an endpoint without a method: `client.Do(ctx, "GET", "/api/v2/…", nil, &out)`. Optional fields in `api.*` types are pointers — helpers `itemshop.String/Bool/Float/Int/Ptr`.

## Errors

Every failure is an `*itemshop.Error` (the `storefront` package uses the same type):

```go theme={null}
var e *itemshop.Error
if errors.As(err, &e) {
	switch e.Code { // backend code (e.g. "LEGAL_CONSENT_REQUIRED") or an SDK code
	case itemshop.CodeRateLimited:
		time.Sleep(e.RetryAfter)
	case itemshop.CodeUnauthorized:
		// wrong / revoked key
	}
}
if errors.Is(err, itemshop.ErrNotFound) { /* matches by code or HTTP status */ }
```

SDK codes: `BAD_REQUEST`, `UNAUTHORIZED`, `FORBIDDEN`, `NOT_FOUND`, `CONFLICT`, `VALIDATION_FAILED`, `RATE_LIMITED`, `SERVER_ERROR`, `NETWORK_ERROR`, `TIMEOUT`, `ABORTED`… — the same as in the TypeScript SDK.

## Retries, timeouts, idempotency

* 2 retries by default (`WithMaxRetries`), backoff 300 ms·2ⁿ (max 5 s) with jitter; `Retry-After` replaces the delay.
* GET/HEAD and requests carrying an `Idempotency-Key` (`Orders.Create`, `Checkout.Create`, `itemshop.WithIdempotencyKey`) are retried on network errors, timeouts and 408/425/429/500/502/503/504.
* Other writes — only on 429.
* `WithTimeout` limits one attempt (30 s default); the `context` bounds the whole call including retries.
* Options: `WithBaseURL` (or `$ITEMSHOP_API_BASE`), `WithHTTPClient`, `WithUserAgent`, `WithLocale`, `WithHeader`.

## Webhooks

The backend sends no signed webhooks to shop owners (notifications go to Discord — see [Webhooks](https://andcze.mintlify.site/en/developers/webhooks.md)), so the SDK has no signature verifier.

> **[Storefront API](https://andcze.mintlify.site/en/developers/storefront-api.md)**
>
> The endpoints under the SDK.

> **[Errors and limits](https://andcze.mintlify.site/en/developers/errors-and-limits.md)**
>
> Error codes and rate limits.


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