> ## 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.

# .NET

> Un client .NET pour l'API StockShift. Il a une méthode pour chaque opération de la référence de l'API et un modèle pour chaque requête et réponse. Le tout est généré à partir du document OpenAPI de l'API.

Il cible .NET 10 et .NET Standard 2.0, donc il fonctionne aussi sur .NET 8 et sur .NET Framework 4.6.2 ou plus récent. Il est compatible avec Native AOT et le découpage (trimming) sur .NET 10.

## Installation

```bash theme={null}
dotnet add package StockShift.Sdk
```

## Démarrage rapide

Créez un article, puis listez le stock en main :

```csharp theme={null}
using StockShift;
using StockShift.Models;

var stockshift = new StockShiftClient(Environment.GetEnvironmentVariable("STOCKSHIFT_TOKEN")!);

await stockshift.Catalog.CreateItemAsync(new CreateItemRequest
{
    Sku = "BOLT-M4",
    Name = "M4 hex bolt",
    Type = ItemType.Stocked,
    MakeOrBuy = MakeOrBuy.Buy,
});

await foreach (var row in stockshift.Inventory.ListStockOnHandAsync())
{
    Console.WriteLine($"{row.Sku} {row.LocationCode} {row.AvailableToPromise}");
}
```

Créez un seul client et réutilisez-le. Il est sûr entre plusieurs fils d'exécution (thread safe).

## Injection de dépendances

Dans une application ASP.NET Core ou toute application qui utilise `Microsoft.Extensions.DependencyInjection`, inscrivez le client avec `AddStockShift()`. Il envoie ses appels par `IHttpClientFactory` :

```csharp theme={null}
builder.Services.AddStockShift(options => options.Token = builder.Configuration["StockShift:Token"]);
```

Recevez ensuite `StockShiftClient` dans un constructeur. `AddStockShift()` renvoie le `IHttpClientBuilder`, ce qui vous permet d'y ajouter vos propres gestionnaires, par exemple pour la journalisation.

## Authentification

Passez une clé d'API ou un jeton d'accès OAuth comme jeton. Créez une clé d'API dans l'application sous Paramètres > Accès > Clés d'API. La clé agit au nom du membre qui l'a créée, et un appel exige à la fois l'autorisation du membre et l'une des portées de la clé.

Pour un jeton OAuth qui expire, définissez plutôt `TokenProvider`. Le client l'appelle avant chaque requête :

```csharp theme={null}
var stockshift = new StockShiftClient(new StockShiftOptions
{
    TokenProvider = cancellationToken => tokens.GetCurrentAsync(cancellationToken),
});
```

Autres options :

| Option | Valeur par défaut | Signification |
| - | - | - |
| `BaseAddress` | `https://app.stockshift.io/api/v1` | L'adresse de l'API. |
| `MaxRetries` | `2` | Nombre de nouvelles tentatives pour un appel qui peut être répété. |
| `Timeout` | 60 secondes | Durée d'attente pour chaque tentative. |
| `MaxRetryAfter` | 60 secondes | Le plus long `Retry-After` qui vaut la peine d'attendre. |
| `TimeProvider` | `TimeProvider.System` | L'horloge des délais d'expiration et des attentes. Remplacez-la dans les tests. |

## Faire des appels

Chaque domaine de l'API est une propriété, comme `Catalog` ou `Inventory`, avec une méthode pour chaque opération. Les paramètres de chemin viennent en premier, puis le corps, puis la chaîne de requête. Chaque méthode prend un `CancellationToken` en dernier :

```csharp theme={null}
var item = await stockshift.Catalog.GetItemAsync(itemId, cancellationToken: cancellationToken);
Console.WriteLine(item.Sku);

var page = await stockshift.Catalog.ListItemsPageAsync(new ListItemsQuery { Search = "bolt", Status = ItemStatus.Active }, cancellationToken: cancellationToken);
```

Le commentaire de documentation de chaque méthode nomme son chemin, comme `GET /catalog/items/{item}`. Un appel renvoie les `data` de la réponse. Un appel dont la réponse est vide renvoie une `Task`. Un export CSV renvoie son texte. Un fichier ou un PDF revient sous forme de `StockShiftContent`, qui contient le flux non lu. Libérez-le (Dispose) quand vous avez terminé.

Une valeur tirée d'un ensemble fixe, comme le type d'un article, est une `string`, et l'ensemble est une classe de constantes, comme `ItemType`. Une valeur ajoutée plus tard par l'API se lit quand même.

Un champ de requête qui peut être omis ou envoyé à null est un `Opt<T>`. Laissez la propriété non définie pour omettre le champ : l'API garde alors la valeur actuelle. Réglez-la à `null` pour envoyer un null explicite :

```csharp theme={null}
// Takes the device off its location and keeps its offline grace as it is.
await stockshift.Devices.RenameDeviceAsync(deviceId, new UpdateDeviceRequest { LocationId = null }, cancellationToken: cancellationToken);
```

## Pagination

Une liste qui peut grossir renvoie une page à la fois. Sa méthode renvoie un `IAsyncEnumerable` qui suit les curseurs et produit chaque enregistrement :

```csharp theme={null}
await foreach (var found in stockshift.Catalog.ListItemsAsync(new ListItemsQuery { Search = "bolt" }))
{
    Console.WriteLine(found.Sku);
}
```

La méthode qui se termine par `PageAsync`, comme `ListItemsPageAsync`, récupère une seule page. Pour paginer vous-même, renvoyez le `NextCursor` de chaque page dans `After` de la requête jusqu'à ce qu'il soit null.

## Erreurs

Un appel qui échoue lève une `StockShiftApiException` qui contient le corps des détails du problème RFC 9457. Basez votre logique sur `Code`, qui est stable. Le détail est rédigé pour des humains et peut changer.

```csharp theme={null}
try
{
    await stockshift.Catalog.CreateItemAsync(request);
}
catch (StockShiftApiException error) when (error.Code == "validation_failed")
{
    foreach (var (field, messages) in error.Errors)
    {
        Console.WriteLine($"{field}: {string.Join(" ", messages)}");
    }
}
```

`StockShiftApiException` a aussi `StatusCode`, `Problem` et `Headers`. Un appel qui n'obtient aucune réponse, parce que le réseau a fait défaut ou que la tentative a expiré, lève une `StockShiftConnectionException`. Les deux héritent de `StockShiftException`. L'annulation du jeton lève une `OperationCanceledException`, comme d'habitude en .NET.

## Nouvelles tentatives et clés d'idempotence

Le client réessaie un `429` après le délai indiqué dans `Retry-After`. Il le fait pour toutes les méthodes, parce que l'API n'a pas exécuté l'appel. Si `Retry-After` dépasse `MaxRetryAfter`, il lève plutôt une exception.

Un `5xx` ou une défaillance réseau est réessayé pour `GET`, `PUT` et `DELETE`, avec un court délai progressif. Un `POST` ou un `PATCH` n'est réessayé que si vous lui donnez une clé d'idempotence, pour qu'une nouvelle tentative ne puisse pas appliquer la modification deux fois :

```csharp theme={null}
await stockshift.Integrations.PushStockNowAsync(connectionId, new RequestOptions { IdempotencyKey = Guid.NewGuid().ToString() });
```

Utilisez une nouvelle clé pour chaque modification que vous voulez faire. Les points de terminaison qui tiennent compte de la clé l'indiquent dans la référence de l'API.

## Webhooks

Vérifiez l'en-tête `StockShift-Signature` avant de faire confiance à une livraison. `StockShiftWebhook.Verify()` a besoin du corps brut, exactement tel qu'il est arrivé :

```csharp theme={null}
app.MapPost("/webhooks/stockshift", async (HttpRequest request) =>
{
    using var reader = new StreamReader(request.Body);
    var payload = await reader.ReadToEndAsync();

    try
    {
        var webhookEvent = StockShiftWebhook.Verify(payload, request.Headers[StockShiftWebhook.SignatureHeader], secret);
        if (webhookEvent is InventoryStockAdjustedEvent adjusted)
        {
            Console.WriteLine($"{adjusted.Data.ItemId} {adjusted.Data.Quantity}");
        }

        return Results.NoContent();
    }
    catch (WebhookVerificationException)
    {
        return Results.BadRequest();
    }
});
```

Chaque type d'événement a sa propre classe, comme `InventoryStockAdjustedEvent`. Un type que ce paquet ne connaît pas encore arrive sous forme de `UnknownWebhookEvent`.

Elle refuse une livraison de plus de cinq minutes. Passez `tolerance` pour changer ce délai. Les nouvelles tentatives d'un événement gardent son `Id` : conservez-le et ignorez les événements que vous avez déjà traités.

Pour tester votre propre récepteur, `StockShiftWebhook.Sign()` signe une charge utile de la même façon que StockShift.

## Versions

La version majeure change quand l'API évolue d'une façon qui peut briser votre code, comme un champ retiré ou un nouveau paramètre obligatoire. Les nouveaux points de terminaison et champs arrivent dans des versions mineures. `StockShiftClient.ApiVersion` contient la version de la référence de l'API à partir de laquelle le paquet a été construit.


## Related topics

- [StockShift pour les développeurs](https://docs.stockshift.io/fr-ca/index.md)
- [SDK](https://docs.stockshift.io/fr-ca/sdks/index.md)
- [Rechercher un produit dans la bibliothèque](https://docs.stockshift.io/fr-ca/api-reference/bibliothèque-de-produits/rechercher-un-produit-dans-la-bibliothèque.md)


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