# GET /partner/webhooks

List the notification subscriptions recorded in your brand's name, page by page. Requires the webhooks:read right.

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

---

By the end of this page, you will know how to list the notification
subscriptions recorded in your brand's name and to walk through that list page
by page.

Full address:

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

The same endpoint also answers without the `/v1` prefix, at
`https://api.sealtrust.io/partner/webhooks`. Both addresses call the same code.
Use the `/v1` form for a new integration.

## Authorization

API key in the `Authorization` header, in `Bearer` format, carrying the
`webhooks:read` right. A key that does not carry that right receives a 403 whose
message names the missing right.

A key belongs to a single brand. This list therefore contains only the
subscriptions of the key's brand, and no other.

This read stays open whatever your plan. If your plan no longer includes
notifications, you keep seeing which reception points are recorded in your name.
It is creation and modification that require the plan.

## Call limit

Throughput is measured over a fixed 60 second window. The value applied is the
one of your plan, or the one set on your account if we have set one. In the
absence of both, the fallback value is 120 calls per window.

Two counters stack, with the same ceiling: one per key, one for the sum of all
your brand's keys. Creating additional keys therefore does not increase the
total allowed throughput.

The limit is checked before the key right check and before any database read. A
call refused with a 403 for a missing right has therefore already consumed one
unit of the current window's budget.

A 200 response carries four headers, which describe the more constraining
counter of the two.

| Header | Content |
| --- | --- |
| `X-RateLimit-Limit` | the ceiling applied over the window |
| `X-RateLimit-Remaining` | what is left to you in the current window |
| `X-RateLimit-Reset` | the timestamp of the end of the window, in seconds |
| `X-RateLimit-Scope` | `key` or `brand`, the counter that served as the reference |

These four headers accompany the 200 response and the 429 response. On the other
response codes, do not expect them: a key that is absent, unknown, revoked or
expired is refused before any counting, and the other refusals do not report
these values.

> [!ATTENTION] Three of these headers are emitted twice, with different values
> `X-RateLimit-Limit`, `X-RateLimit-Remaining` and `X-RateLimit-Reset` appear
> twice in the same response. The first occurrence of each name is the one in
> the table above: your key and your brand. The second comes from a second
> counter, kept per IP address, whose values do not describe the ceiling of your
> key. `X-RateLimit-Scope` appears only once.
>
> Always read the first occurrence. Most HTTP libraries join the occurrences of
> the same header with a comma, and you then get two numbers instead of one.
> Split on the comma and keep the first piece. This double emission is a known
> defect on our side.

A refusal returns 429 with `Retry-After`, expressed in seconds remaining in the
current window. That value is never lower than 1.

> [!INFO] This endpoint does not consume the daily quota of your key
> The daily quota is consumed on the batch mint,
> [`POST /v1/partner/mint/batch`](/en/reference/post-partner-mint-batch/), per
> item, and on the sell-out declaration,
> [`POST /v1/partner/sellout`](/en/reference/post-partner-sellout/), per call.
> The five notification subscription endpoints do not touch it. Only the
> throughput limit applies here.

## Path and query parameters

This endpoint has no path parameter.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `skip` | `integer` | no | The number of subscriptions to skip before starting the page. Is 0 by default. A negative value is refused with a 422. |
| `limit` | `integer` | no | The maximum number of subscriptions to return. Is 20 by default. The minimum is 1, the maximum is 100. A value outside these bounds is refused with a 422, with no silent truncation. |

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Authorization` | `string` | yes | `Bearer` followed by your API key. |

## Request body

This endpoint has no request body. All the information you send fits in the two
query parameters above.

## Example request

The first page, twenty subscriptions at most.

:::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 is emitted twice. requests joins the two values
# with a comma: the first one is your key's, keep that one.
restant = response.headers["X-RateLimit-Remaining"].split(",")[0].strip()
print(restant)

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

To read the next page, raise `skip` by the value of `limit`: `skip=20` with
`limit=20`, then `skip=40`, and so on until `items` is empty. The `total` field
gives you the number of subscriptions to walk through.

## Example response

HTTP code `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
}
```

The list is paginated, and sorted on the creation date, from the most recent to
the oldest.

The response has two fields and nothing else.

| Field | Type | Description |
| --- | --- | --- |
| `items` | `array` | The subscriptions of the page, from the most recent to the oldest. |
| `total` | `integer` | The total number of subscriptions of your brand, across all pages, active as well as turned off. |

Each entry of `items` has eight fields.

| Field | Type | Description |
| --- | --- | --- |
| `id` | `integer` | The identifier of the subscription. Pass it in the path of [`GET /v1/partner/webhooks/{webhook_id}`](/en/reference/get-partner-webhooks-id/), of [`PUT /v1/partner/webhooks/{webhook_id}`](/en/reference/put-partner-webhooks-id/) and of [`DELETE /v1/partner/webhooks/{webhook_id}`](/en/reference/delete-partner-webhooks-id/). |
| `url` | `string` | The address that receives the deliveries. It always starts with `https://`. |
| `event_types` | `array` | The event types this subscription is registered for. An empty list means that no event will be delivered. |
| `brand_id` | `integer` | The number of your brand. It is identical on every entry. |
| `is_active` | `boolean` | `false` when the subscription is turned off. |
| `health` | `string` | `healthy` or `degraded`. See below. |
| `created_at` | `string` | The creation date of the subscription, in ISO 8601 format with time zone. |
| `updated_at` | `string` | The date of the last modification, in ISO 8601 format with time zone. |

> [!ATTENTION] This list names the field `event_types`, the three other endpoints that return a subscription name it `events`
> [`POST /v1/partner/webhooks`](/en/reference/post-partner-webhooks/),
> `GET /v1/partner/webhooks/{webhook_id}` and
> `PUT /v1/partner/webhooks/{webhook_id}` return the list of events under the
> name `events`. This page returns it under the name `event_types`. The content
> is the same. If you read both forms in the same code, plan for both names.
> `DELETE /v1/partner/webhooks/{webhook_id}` answers 204 with no body, so it
> names no field.

`health` is `healthy` at creation. It moves to `degraded` when we give up the
delivery attempts on that address. It goes back to `healthy` on the first
successful delivery that follows.

The signing secret of a subscription is never returned by this list, nor by any
other read endpoint.

> [!INFO] `skip` and `limit` are not sent back to you
> You send them, they are applied, and the response does not repeat them. Keep
> the position of your pagination in your own code.

## Errors

The body of an error response carries a `detail` field. Depending on the case,
that field contains a sentence or a list.

| Code | Condition | What to do |
| --- | --- | --- |
| 401 | The `Authorization` header is absent. The response also carries `WWW-Authenticate: Bearer`. | Add the header. |
| 401 | The `Authorization` header does not start with `Bearer ` followed by a space. The response also carries `WWW-Authenticate: Bearer`. | Correct the form of the header. |
| 401 | The key sent is empty or has fewer than 40 characters. `detail` is `Invalid API key format`. This response does not carry `WWW-Authenticate`. | Send the complete secret, with no space and no line break. |
| 401 | The key sent is unknown. `detail` is `Invalid API key`. | Check that you are using the right key, and that it has not been replaced. |
| 403 | The key is no longer active, because it has been revoked. The message gives its state. | Create a new key in the console. |
| 403 | The key has reached its expiration date. | Create a new key. The old one will never become valid again. |
| 403 | The key does not carry the `webhooks:read` right. The message names the missing right. | Create a key carrying that right. The rights of an existing key cannot be modified. |
| 422 | `skip` is negative, `limit` is lower than 1 or greater than 100, or one of the two values is not an integer. `detail` is a list that names the faulty parameter. | Correct the value. The upper bound of `limit` is 100. |
| 422 | A pagination value exceeds what the database accepts as an integer. The message is generic and does not name the parameter. The response carries an `X-Request-Id` header. | Reduce `skip`. Normal pagination stays far below that bound. |
| 429 | The throughput limit of the key is reached. The `Retry-After` header and the `X-RateLimit-*` family accompany the response, with `X-RateLimit-Scope: key`. | Wait the number of seconds indicated by `Retry-After`, then try again. |
| 429 | The throughput limit of the brand is reached, all keys taken together. `X-RateLimit-Scope` is `brand`. | Wait the number of seconds indicated by `Retry-After`. Creating an additional key does not raise that ceiling. |
| 500 | An unexpected error occurred while handling your call. The body is `{"detail": "Internal Server Error"}` and the response carries an `X-Request-Id` header. | Try again. If the error persists, contact support giving the value of `X-Request-Id`. |
| 503 | The service that keeps the throughput counters is momentarily unavailable. The call is refused without being counted. | Try again in a few moments. No data was read or modified. |

This endpoint never returns 404. A brand with no subscription at all receives a
200 with an empty `items` and `total` at 0.

## See also

- [`POST /partner/webhooks`](/en/reference/post-partner-webhooks/),
  record an HTTPS address that will receive your events.
- [`GET /partner/webhooks/{webhook_id}`](/en/reference/get-partner-webhooks-id/),
  read a subscription and its delivery state.
- [`PUT /partner/webhooks/{webhook_id}`](/en/reference/put-partner-webhooks-id/),
  modify the address, the events or the secret of a subscription.
- [`DELETE /partner/webhooks/{webhook_id}`](/en/reference/delete-partner-webhooks-id/),
  delete a subscription and the signing secret attached to it.
- [Receive events by webhook](/en/webhooks/),
  create a subscription, verify a signature, catch up on lost events.
