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

# Go

> A Go client for the StockShift API. It has a method for every operation in the API reference and a Go type for each request and response, all generated from the API's OpenAPI document.

It needs Go 1.26 or later. It has no dependencies outside the standard library.

## Install

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

```go theme={null}
import stockshift "github.com/StockShift/go-sdk"
```

## Quickstart

Create an item, then list stock on hand:

```go theme={null}
client := stockshift.NewClient(stockshift.WithToken(os.Getenv("STOCKSHIFT_TOKEN")))

item, err := client.Catalog.CreateItem(ctx, &stockshift.CreateItemRequest{
	SKU:       "BOLT-M4",
	Name:      "M4 hex bolt",
	Type:      stockshift.ItemTypeStocked,
	MakeOrBuy: stockshift.MakeOrBuyBuy,
})
if err != nil {
	return err
}

for row, err := range client.Inventory.ListStockOnHandAll(ctx, nil) {
	if err != nil {
		return err
	}
	fmt.Println(row.SKU, row.LocationCode, row.AvailableToPromise)
}
```

## Authentication

Pass an API key or an OAuth access token with `WithToken`. Create an API key in the app under Settings > Access > API keys. The key acts as the member who made it, and a call needs both the member's permission and one of the key's scopes.

For an OAuth token that expires, pass a function with `WithTokenFunc`. The client calls it before each request, and an error it returns is the error of the call:

```go theme={null}
client := stockshift.NewClient(stockshift.WithTokenFunc(func(ctx context.Context) (string, error) {
	return tokens.Current(ctx)
}))
```

Other options:

| Option | Default | Meaning |
| - | - | - |
| `WithBaseURL` | `https://app.stockshift.io/api/v1` | Where the API is. |
| `WithHTTPClient` | an `http.Client` with a 60 second timeout | The client that sends requests. Its `Timeout` limits each attempt. |
| `WithMaxRetries` | `2` | Retries for a call that can be retried. |
| `WithMaxRetryAfter` | one minute | The longest `Retry-After` worth waiting for. |
| `WithHeader` | none | A header sent on every call. |

A `Client` is safe to use from many goroutines. Make one and share it.

## Making calls

Each area of the API is a field of the client, such as `Catalog` or `Inventory`, with a method for each operation. Every method takes a `context.Context` first, then the path parameters, then the body, then the query parameters:

```go theme={null}
item, err := client.Catalog.GetItem(ctx, "01J8QZ4M...")

page, err := client.Catalog.ListItems(ctx, &stockshift.CatalogListItemsParams{
	Search: stockshift.Ptr("bolt"),
	Status: stockshift.Ptr(stockshift.ItemStatusActive),
})
```

Every method's doc comment names its path, such as `GET /catalog/items/{item}`. A method returns the `data` of the answer as a generated type. An empty answer returns only an error, a CSV export its bytes and a file the `*http.Response`, whose body you close.

Cancel the context to stop a call, retries and waits included.

### Optional fields

A query parameter you can leave out is a pointer. `stockshift.Ptr` makes one from a value.

A request body field you can leave out is an `Opt`. Its zero value leaves the field out, `stockshift.Value(v)` sends `v` and `stockshift.Null[T]()` sends `null`, which clears the field where the API allows it:

```go theme={null}
_, err := client.Catalog.UpdateItem(ctx, id, &stockshift.ItemFieldsRequest{
	SKU:       "BOLT-M4",
	Name:      "M4 hex bolt",
	Type:      stockshift.ItemTypeStocked,
	MakeOrBuy: stockshift.MakeOrBuyBuy,
	Brand:     stockshift.Null[string](),
})
```

### Other endpoints

`client.Do` calls any path and decodes the JSON answer into a value you pass. Use it for an endpoint added to the API after this version of the package:

```go theme={null}
var out struct {
	Data stockshift.ItemResource `json:"data"`
}
err := client.Do(ctx, http.MethodGet, "/catalog/items/"+id, nil, nil, &out)
```

## Pagination

A list that can grow returns one page at a time. Each paged list has a second method ending in `All` that returns an `iter.Seq2`. It follows the cursors and yields each record:

```go theme={null}
for item, err := range client.Catalog.ListItemsAll(ctx, &stockshift.CatalogListItemsParams{Search: stockshift.Ptr("bolt")}) {
	if err != nil {
		return err
	}
	fmt.Println(item.SKU)
}
```

It fetches the next page only when the loop needs it, so a `break` stops it. An error ends the loop. To page by hand, set `After` to each page's `NextCursor` until it is `nil`.

## Errors

A call the API refuses returns an `*APIError` that holds the RFC 9457 problem details body. Branch on `Code`, which is stable. `Problem.Detail` is written for people and may change.

```go theme={null}
_, err := client.Catalog.CreateItem(ctx, body)

var apiErr *stockshift.APIError
if errors.As(err, &apiErr) && apiErr.Code == "validation_failed" {
	fmt.Println(apiErr.Problem.Errors) // map[sku:[Another item already has the SKU BOLT-M4.]]
}
```

`APIError` also has `StatusCode` and `Header`. A call that gets no answer, because the network failed or the attempt timed out, returns a `*ConnectionError` that wraps the cause. When the context ends, the call returns the context's error.

## Retries and idempotency keys

The client retries a `429` after the time in `Retry-After`. It does this for every method, because the API did not run the call. If `Retry-After` is longer than `WithMaxRetryAfter`, it returns the error instead.

A `5xx` or a network failure is retried for `GET`, `PUT` and `DELETE`, with a short backoff. A `POST` or `PATCH` is retried only when you give it an idempotency key, so a retry cannot make the change twice:

```go theme={null}
run, err := client.Integrations.PushStockNow(ctx, connectionID, stockshift.IdempotencyKey(rand.Text()))
```

Use a new key for each change you mean to make. The endpoints that honor the key say so in the API reference. `CallMaxRetries` and `CallHeader` change a single call in the same way.

## Webhooks

Check the `StockShift-Signature` header before you trust a delivery. `WebhookVerifier.Verify` needs the raw body, exactly as it arrived:

```go theme={null}
verifier := stockshift.WebhookVerifier{Secret: os.Getenv("STOCKSHIFT_WEBHOOK_SECRET")}

http.HandleFunc("POST /webhooks/stockshift", func(w http.ResponseWriter, r *http.Request) {
	body, err := io.ReadAll(r.Body)
	if err != nil {
		http.Error(w, "", http.StatusBadRequest)
		return
	}
	event, err := verifier.Verify(body, r.Header.Get(stockshift.SignatureHeader))
	if err != nil {
		http.Error(w, "", http.StatusBadRequest)
		return
	}
	if event.Type == stockshift.EventInventoryStockAdjusted {
		var data stockshift.InventoryStockAdjustedData
		if err := json.Unmarshal(event.Data, &data); err != nil {
			http.Error(w, "", http.StatusBadRequest)
			return
		}
		fmt.Println(data.ItemID, data.Quantity)
	}
	w.WriteHeader(http.StatusNoContent)
})
```

It refuses a delivery more than five minutes old. Set `Tolerance` to change that. Retries of an event keep its `ID`, so store it and skip events you have handled.

Each event type has a constant, such as `EventInventoryStockAdjusted`, whose doc comment names the type its `Data` decodes into. To test your own receiver, `SignWebhook` signs a payload the same way StockShift does.

## Versions

The module follows semantic versioning. The major version moves when the API changes in a way that can break your code, such as a removed field or a new required parameter. In Go a new major version also changes the import path, such as `github.com/StockShift/go-sdk/v2`. New endpoints and fields come in minor versions. `APIVersion` holds the version of the API reference the module was built from.

The two newest Go releases are supported, as the Go team supports them.


## Related topics

- [Update the Inventory settings, such as whether stock may go below zero](https://docs.stockshift.io/api-reference/inventory-settings/update-the-inventory-settings-such-as-whether-stock-may-go-below-zero.md)
- [Laravel](https://docs.stockshift.io/sdks/laravel.md)
- [SDKs](https://docs.stockshift.io/sdks/index.md)


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