# GET /partner/webhooks

Lister les abonnements aux notifications enregistrés au nom de votre marque, page par page. Droit webhooks:read.

Source : https://docs.sealtrust.io/reference/get-partner-webhooks/

---

En quittant cette page, vous saurez lister les abonnements aux notifications
enregistrés au nom de votre marque et parcourir cette liste page par page.

Adresse complète :

```http
GET https://api.sealtrust.io/v1/partner/webhooks
```

Le même point d'entrée répond aussi sans le préfixe `/v1`, à
`https://api.sealtrust.io/partner/webhooks`. Les deux adresses appellent le
même code. Utilisez la forme `/v1` pour une nouvelle intégration.

## Autorisation

Clef d'API dans l'en-tête `Authorization`, au format `Bearer`, portant le droit
`webhooks:read`. Une clef qui ne porte pas ce droit reçoit un 403 dont le
message nomme le droit manquant.

Une clef appartient à une seule marque. Cette liste ne contient donc que les
abonnements de la marque de la clef, et aucun autre.

Cette lecture reste ouverte quelle que soit votre offre. Si votre offre ne
comprend plus les notifications, vous continuez à voir quels points de
réception sont enregistrés en votre nom. Ce sont la création et la
modification qui exigent l'offre.

## Plafond d'appels

Le débit est mesuré sur une fenêtre fixe de 60 secondes. La valeur appliquée
est celle de votre offre, ou celle posée sur votre compte si nous en avons posé
une. En l'absence des deux, la valeur de repli est de 120 appels par fenêtre.

Deux compteurs se superposent, avec le même plafond : un par clef, un pour la
somme de toutes les clefs de votre marque. Créer des clefs supplémentaires
n'augmente donc pas le débit total autorisé.

Le plafond est vérifié avant le contrôle du droit de la clef et avant toute
lecture en base. Un appel refusé en 403 pour droit manquant a donc déjà
consommé une unité du budget de la fenêtre en cours.

Une réponse 200 porte quatre en-têtes, qui décrivent le compteur le plus
contraignant des deux.

| En-tête | Contenu |
| --- | --- |
| `X-RateLimit-Limit` | le plafond appliqué sur la fenêtre |
| `X-RateLimit-Remaining` | ce qu'il vous reste dans la fenêtre en cours |
| `X-RateLimit-Reset` | l'horodatage de fin de la fenêtre, en secondes |
| `X-RateLimit-Scope` | `key` ou `brand`, le compteur qui a servi de référence |

Ces quatre en-têtes accompagnent la réponse 200 et la réponse 429. Sur les
autres codes de réponse, ne les attendez pas : une clef absente, inconnue,
révoquée ou expirée est refusée avant tout comptage, et les autres refus ne
reportent pas ces valeurs.

> [!ATTENTION] Trois de ces en-têtes sont émis deux fois, avec des valeurs différentes
> `X-RateLimit-Limit`, `X-RateLimit-Remaining` et `X-RateLimit-Reset`
> apparaissent deux fois dans la même réponse. La première occurrence de chaque
> nom est celle du tableau ci-dessus : votre clef et votre marque. La seconde
> vient d'un second compteur, tenu par adresse IP, dont les valeurs ne
> décrivent pas le plafond de votre clef. `X-RateLimit-Scope` n'apparaît
> qu'une fois.
>
> Lisez toujours la première occurrence. La plupart des bibliothèques HTTP
> joignent les occurrences d'un même en-tête par une virgule, et vous obtenez
> alors deux nombres au lieu d'un seul. Coupez sur la virgule et gardez le
> premier morceau. Cette double émission est un défaut connu de notre côté.

Un refus renvoie 429 avec `Retry-After`, exprimé en secondes restantes dans la
fenêtre en cours. Cette valeur n'est jamais inférieure à 1.

> [!INFO] Ce point d'entrée ne consomme pas le quota quotidien de votre clef
> Le quota quotidien se consomme sur la frappe en lot,
> [`POST /v1/partner/mint/batch`](/reference/post-partner-mint-batch/), par
> article, et sur la déclaration de vente,
> [`POST /v1/partner/sellout`](/reference/post-partner-sellout/), par appel. Les
> cinq points d'entrée d'abonnement aux notifications n'y touchent pas. Seul le
> plafond de débit s'applique ici.

## Paramètres de chemin et de requête

Ce point d'entrée n'a pas de paramètre de chemin.

| Nom | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `skip` | `integer` | non | Le nombre d'abonnements à sauter avant de commencer la page. Vaut 0 par défaut. Une valeur négative est refusée en 422. |
| `limit` | `integer` | non | Le nombre d'abonnements à rendre au maximum. Vaut 20 par défaut. Le minimum est 1, le maximum est 100. Une valeur en dehors de ces bornes est refusée en 422, sans troncature silencieuse. |

### En-têtes

| Nom | Type | Obligatoire | Description |
| --- | --- | --- | --- |
| `Authorization` | `string` | oui | `Bearer` suivi de votre clef d'API. |

## Corps de la requête

Ce point d'entrée n'a pas de corps de requête. Toute l'information que vous
envoyez tient dans les deux paramètres de requête ci-dessus.

## Requête d'exemple

La première page, vingt abonnements au maximum.

:::onglets
```bash title="curl"
curl -i -X GET "https://api.sealtrust.io/v1/partner/webhooks?skip=0&limit=20" \
  -H "Authorization: Bearer st_test_0000000000000000000000000000000000000000000000"
```
```typescript
import { SealTrustClient } from "@sealtrust-io/sdk";

const sealtrust = new SealTrustClient({
  apiKey: "st_test_0000000000000000000000000000000000000000000000",
});

const page = await sealtrust.webhooks.list({ skip: 0, limit: 20 });

console.log(page.total);
for (const abonnement of page.items) {
  console.log(
    abonnement.id,
    abonnement.url,
    abonnement.event_types.join(", "),
    abonnement.health,
  );
}
```
```python
import requests

response = requests.get(
    "https://api.sealtrust.io/v1/partner/webhooks",
    headers={
        "Authorization": "Bearer st_test_0000000000000000000000000000000000000000000000",
    },
    params={"skip": 0, "limit": 20},
    timeout=30,
)

print(response.status_code)

# X-RateLimit-Remaining est émis deux fois. requests joint les deux valeurs
# par une virgule : la première est celle de votre clef, gardez celle-là.
restant = response.headers["X-RateLimit-Remaining"].split(",")[0].strip()
print(restant)

print(response.json())
```
:::

Pour lire la page suivante, augmentez `skip` de la valeur de `limit` : `skip=20`
avec `limit=20`, puis `skip=40`, et ainsi de suite jusqu'à ce que `items` soit
vide. Le champ `total` vous donne le nombre d'abonnements à parcourir.

## Réponse d'exemple

Code HTTP `200`.

```json
{
  "items": [
    {
      "id": 41,
      "url": "https://exemple.test/sealtrust/evenements",
      "event_types": [
        "product.minted",
        "batch.completed",
        "batch.failed"
      ],
      "brand_id": 12,
      "is_active": true,
      "health": "healthy",
      "created_at": "2026-08-18T09:14:02.117043+00:00",
      "updated_at": "2026-08-18T09:14:02.117043+00:00"
    },
    {
      "id": 39,
      "url": "https://exemple.test/sealtrust/retours",
      "event_types": [
        "return.requested",
        "return.completed"
      ],
      "brand_id": 12,
      "is_active": false,
      "health": "degraded",
      "created_at": "2026-08-11T16:40:55.902881+00:00",
      "updated_at": "2026-08-19T07:02:31.448190+00:00"
    }
  ],
  "total": 2
}
```

La liste est paginée, et triée sur la date de création, du plus récent au plus
ancien.

La réponse compte deux champs et rien d'autre.

| Champ | Type | Description |
| --- | --- | --- |
| `items` | `array` | Les abonnements de la page, du plus récent au plus ancien. |
| `total` | `integer` | Le nombre total d'abonnements de votre marque, toutes pages confondues, actifs comme éteints. |

Chaque entrée de `items` compte huit champs.

| Champ | Type | Description |
| --- | --- | --- |
| `id` | `integer` | L'identifiant de l'abonnement. Passez-le dans le chemin de [`GET /v1/partner/webhooks/{webhook_id}`](/reference/get-partner-webhooks-id/), de [`PUT /v1/partner/webhooks/{webhook_id}`](/reference/put-partner-webhooks-id/) et de [`DELETE /v1/partner/webhooks/{webhook_id}`](/reference/delete-partner-webhooks-id/). |
| `url` | `string` | L'adresse qui reçoit les livraisons. Elle commence toujours par `https://`. |
| `event_types` | `array` | Les types d'événements auxquels cet abonnement est inscrit. Une liste vide veut dire qu'aucun événement ne sera livré. |
| `brand_id` | `integer` | Le numéro de votre marque. Il est identique sur toutes les entrées. |
| `is_active` | `boolean` | `false` quand l'abonnement est éteint. |
| `health` | `string` | `healthy` ou `degraded`. Voir ci-dessous. |
| `created_at` | `string` | La date de création de l'abonnement, au format ISO 8601 avec fuseau. |
| `updated_at` | `string` | La date de la dernière modification, au format ISO 8601 avec fuseau. |

> [!ATTENTION] Cette liste nomme le champ `event_types`, les trois autres points d'entrée qui rendent un abonnement le nomment `events`
> [`POST /v1/partner/webhooks`](/reference/post-partner-webhooks/),
> `GET /v1/partner/webhooks/{webhook_id}` et
> `PUT /v1/partner/webhooks/{webhook_id}` rendent la liste des événements sous
> le nom `events`. Cette page la rend sous le nom `event_types`. Le contenu est
> le même. Si vous lisez les deux formes dans le même code, prévoyez les deux
> noms. `DELETE /v1/partner/webhooks/{webhook_id}` répond 204 sans corps, il ne
> nomme donc aucun champ.

`health` vaut `healthy` à la création. Il passe à `degraded` quand nous
abandonnons les tentatives de livraison sur cette adresse. Il revient à
`healthy` à la première livraison réussie qui suit.

Le secret de signature d'un abonnement n'est jamais rendu par cette liste, ni
par aucun autre point d'entrée de lecture.

> [!INFO] `skip` et `limit` ne vous sont pas renvoyés
> Vous les envoyez, ils sont appliqués, et la réponse ne les répète pas. Gardez
> la position de votre pagination dans votre propre code.

## Erreurs

Le corps d'une réponse d'erreur porte un champ `detail`. Selon le cas, ce champ
contient une phrase ou une liste.

| Code | Condition | Que faire |
| --- | --- | --- |
| 401 | L'en-tête `Authorization` est absent. La réponse porte aussi `WWW-Authenticate: Bearer`. | Ajoutez l'en-tête. |
| 401 | L'en-tête `Authorization` ne commence pas par `Bearer ` suivi d'un espace. La réponse porte aussi `WWW-Authenticate: Bearer`. | Corrigez la forme de l'en-tête. |
| 401 | La clef envoyée est vide ou compte moins de 40 caractères. `detail` vaut `Invalid API key format`. Cette réponse ne porte pas `WWW-Authenticate`. | Envoyez le secret complet, sans espace ni retour à la ligne. |
| 401 | La clef envoyée est inconnue. `detail` vaut `Invalid API key`. | Vérifiez que vous utilisez la bonne clef, et qu'elle n'a pas été remplacée. |
| 403 | La clef n'est plus active, parce qu'elle a été révoquée. Le message donne son état. | Créez une nouvelle clef dans la console. |
| 403 | La clef a atteint sa date d'expiration. | Créez une nouvelle clef. L'ancienne ne redeviendra jamais valide. |
| 403 | La clef ne porte pas le droit `webhooks:read`. Le message nomme le droit manquant. | Créez une clef portant ce droit. Les droits d'une clef existante ne se modifient pas. |
| 422 | `skip` est négatif, `limit` est inférieur à 1 ou supérieur à 100, ou l'une des deux valeurs n'est pas un entier. `detail` est une liste qui nomme le paramètre fautif. | Corrigez la valeur. La borne haute de `limit` est 100. |
| 422 | Une valeur de pagination dépasse ce que la base accepte comme nombre entier. Le message est générique et ne nomme pas le paramètre. La réponse porte un en-tête `X-Request-Id`. | Réduisez `skip`. Une pagination normale reste très en dessous de cette borne. |
| 429 | Le plafond de débit de la clef est atteint. Les en-têtes `Retry-After` et la famille `X-RateLimit-*` accompagnent la réponse, avec `X-RateLimit-Scope: key`. | Attendez le nombre de secondes indiqué par `Retry-After`, puis réessayez. |
| 429 | Le plafond de débit de la marque est atteint, toutes clefs confondues. `X-RateLimit-Scope` vaut `brand`. | Attendez le nombre de secondes indiqué par `Retry-After`. Créer une clef supplémentaire ne relève pas ce plafond. |
| 500 | Une erreur inattendue s'est produite pendant le traitement de votre appel. Le corps vaut `{"detail": "Internal Server Error"}` et la réponse porte un en-tête `X-Request-Id`. | Réessayez. Si l'erreur persiste, contactez le support en indiquant la valeur de `X-Request-Id`. |
| 503 | Le service qui tient les compteurs de débit est momentanément indisponible. L'appel est refusé sans être compté. | Réessayez dans quelques instants. Aucune donnée n'a été lue ni modifiée. |

Ce point d'entrée ne renvoie jamais 404. Une marque sans aucun abonnement
reçoit un 200 avec `items` vide et `total` à 0.

## Voir aussi

- [`POST /partner/webhooks`](/reference/post-partner-webhooks/),
  enregistrer une adresse HTTPS qui recevra vos événements.
- [`GET /partner/webhooks/{webhook_id}`](/reference/get-partner-webhooks-id/),
  lire un abonnement et son état de livraison.
- [`PUT /partner/webhooks/{webhook_id}`](/reference/put-partner-webhooks-id/),
  modifier l'adresse, les événements ou le secret d'un abonnement.
- [`DELETE /partner/webhooks/{webhook_id}`](/reference/delete-partner-webhooks-id/),
  supprimer un abonnement et le secret de signature qui lui est attaché.
- [Recevoir les événements par webhook](/webhooks/),
  créer un abonnement, vérifier une signature, rattraper les événements
  perdus.
