Skip to main content
It targets .NET 10 and .NET Standard 2.0, so it also runs on .NET 8 and .NET Framework 4.6.2 or later. It works with Native AOT and trimming on .NET 10.

Install

Quickstart

Create an item, then list stock on hand:
Make one client and reuse it. It is thread safe.

Dependency injection

In an ASP.NET Core app or any app that uses Microsoft.Extensions.DependencyInjection, register the client with AddStockShift(). It sends its calls through IHttpClientFactory:
Then take StockShiftClient in a constructor. AddStockShift() returns the IHttpClientBuilder, so you can add your own handlers, such as logging, to it.

Authentication

Pass an API key or an OAuth access token as the token. 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, set TokenProvider instead. The client calls it before each request:
Other options:

Making calls

Each area of the API is a property, such as Catalog or Inventory, with a method for each operation. Path parameters come first, then the body, then the query string. Every method takes a CancellationToken last:
Each method’s doc comment names its path, such as GET /catalog/items/{item}. A call returns the data of the response. A call with an empty response returns a Task. A CSV export returns its text. A file or a PDF comes back as a StockShiftContent, which holds the unread stream. Dispose it when you are done. A value that is one of a fixed set, such as an item’s type, is a string, and the set is a class of constants, such as ItemType. A value the API adds later still reads. A request field that may be left out or sent as null is an Opt<T>. Leave the property unset to leave the field out, so the API keeps what it has. Set it to null to send an explicit null:

Pagination

A list that can grow returns one page at a time. Its method returns an IAsyncEnumerable that follows the cursors and yields each record:
The method ending in PageAsync, such as ListItemsPageAsync, gets one page. To page by hand, send each page’s NextCursor back as After in the query until it is null.

Errors

A failed call throws a StockShiftApiException that holds the RFC 9457 problem details body. Branch on Code, which is stable. The detail is written for people and may change.
StockShiftApiException also has StatusCode, Problem and Headers. A call that gets no answer, because the network failed or the attempt timed out, throws a StockShiftConnectionException. Both extend StockShiftException. Cancelling the token throws an OperationCanceledException, as usual in .NET.

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 MaxRetryAfter, it throws 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:
Use a new key for each change you mean to make. The endpoints that honor the key say so in the API reference.

Webhooks

Check the StockShift-Signature header before you trust a delivery. StockShiftWebhook.Verify() needs the raw body, exactly as it arrived:
Each event type has its own class, such as InventoryStockAdjustedEvent. A type this package does not know yet arrives as an UnknownWebhookEvent. It refuses a delivery more than five minutes old. Pass tolerance to change that. Retries of an event keep its Id, so store it and skip events you have handled. To test your own receiver, StockShiftWebhook.Sign() signs a payload the same way StockShift does.

Versions

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. New endpoints and fields come in minor versions. StockShiftClient.ApiVersion holds the version of the API reference the package was built from.