# GET /partner-portal/interventions

List the interventions your partner account has recorded, from the most recent to the oldest. Partner account session.

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

---

You receive the history of the lifecycle events your account authored: repair,
maintenance, reconditioning, after-sales service, recycling, end of life,
destruction and return. In practice, these are the interventions you recorded
from the partner portal. Each entry carries the product concerned, the proof
level retained at the time of recording, and the date. The list is paginated
and sorted from the most recent to the oldest.

Full address:

```http
GET https://api.sealtrust.io/v1/partner-portal/interventions
```

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

## Authorization

A partner account session, of the repairer or recycler type. You present the
session token obtained at login (`POST /auth/login`) in either of two ways:

- the `Authorization: Bearer <session token>` header, for a call from your own
  code;
- the `access_token` session cookie, which a browser sends on its own when you
  call from the partner portal.

The partner API key does not open this endpoint. It serves the
machine-to-machine surface `/v1/partner/*`, which is a separate surface.

An account whose role is neither repairer nor recycler receives a 403.

> [!INFO] Your accreditations are not re-checked here
> The list keeps the events your account authored. It never contains another
> partner's. If a brand withdraws your accreditation, you keep reading the
> history of the work you already recorded with it. It is searching for a
> product and recording a new intervention that require an active
> accreditation.

## Rate limit

A rate limit applies to this endpoint. It is set for normal use of the portal,
where you search for a product then record an intervention.

Beyond that, the API answers 429. The refusal carries a `Retry-After` header
that gives the number of seconds to wait. Wait that long, then call again.

The limit covers the whole partner portal. Alternating between endpoints
therefore gives you no extra room. Space out your calls instead of sending
them in bursts.

The limit value is not a commitment and can change without notice. Do not hard
code any threshold in your code, rely on `Retry-After`.

This endpoint consumes no product quota and no daily quota.

## Path and query parameters

This endpoint has no path parameter.

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `skip` | `integer` | no | The number of interventions to skip before starting the page. Defaults to 0. Send a negative value and the service answers 422. |
| `limit` | `integer` | no | The maximum number of interventions to return. Defaults to 20. The minimum is 1, the maximum is 100. Go outside those bounds and the service answers 422, with no silent truncation. |

There is no other parameter. The list cannot be filtered by product, by brand,
by intervention type, or by date. Do that filtering in your own code from the
fields returned.

### Headers

| Name | Type | Required | Description |
| --- | --- | --- | --- |
| `Authorization` | `string` | no | `Bearer` followed by your session token. Required if you do not send the session cookie. |
| `Cookie` | `string` | no | The `access_token` cookie, set by login and sent automatically by a browser. Required if you do not send the `Authorization` header. |

A server-to-server call that carries the `Authorization` header is accepted
without an `Origin` or `Referer` header. A browser call that carries the
session cookie must come from an authorized SealTrust domain, otherwise the
response is 403.

## 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 interventions at most.

> [!INFO] The TypeScript tab calls the API with `fetch`
> The TypeScript SDK does not cover the partner portal. It authenticates with
> an API key and exposes verification, products and notification
> subscriptions. Read the TypeScript tab below before copying it: it uses
> `fetch`.

:::onglets
```bash title="curl"
curl -i -X GET "https://api.sealtrust.io/v1/partner-portal/interventions?skip=0&limit=20" \
  -H "Authorization: Bearer DEMO-SESSION-TOKEN"
```
```typescript
const response = await fetch(
  "https://api.sealtrust.io/v1/partner-portal/interventions?skip=0&limit=20",
  {
    method: "GET",
    headers: {
      Authorization: "Bearer DEMO-SESSION-TOKEN",
    },
  },
);

const page = await response.json();

console.log(response.status, page.total);
for (const intervention of page.items) {
  console.log(
    intervention.id,
    intervention.event_type,
    intervention.proof_level,
    intervention.product_name,
    intervention.occurred_at,
  );
}
```
```python
import requests

response = requests.get(
    "https://api.sealtrust.io/v1/partner-portal/interventions",
    headers={
        "Authorization": "Bearer DEMO-SESSION-TOKEN",
    },
    params={"skip": 0, "limit": 20},
    timeout=30,
)

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

To read the next page, increase `skip` by the value of `limit`: `skip=20` with
`limit=20`, then `skip=40`, and so on. The `total` field gives you the number
of interventions to go through.

## Example response

HTTP code `200`.

```json
{
  "total": 2,
  "count": 2,
  "skip": 0,
  "limit": 20,
  "items": [
    {
      "id": 812,
      "product_id": 4471,
      "brand_id": 12,
      "event_type": "repair",
      "proof_level": "customer_code",
      "title": "Gasket replacement",
      "description": "Gasket replaced, water resistance checked at 5 ATM.",
      "event_metadata": {
        "partner_type": "repairer",
        "replaced_parts": "joint torique",
        "cost_eur": 48,
        "notes": "Original part"
      },
      "performed_by": "Example Workshop (accredited repairer)",
      "product_name": "Lampe d'atelier Exemple",
      "occurred_at": "2026-08-19T14:32:07.481920Z",
      "created_at": "2026-08-19T14:32:07.481920Z"
    },
    {
      "id": 796,
      "product_id": 4318,
      "brand_id": 12,
      "event_type": "maintenance",
      "proof_level": "declared",
      "title": "Annual service",
      "description": null,
      "event_metadata": {
        "partner_type": "repairer"
      },
      "performed_by": "Example Workshop (accredited repairer)",
      "product_name": "Lampe d'atelier Exemple",
      "occurred_at": "2026-08-11T09:05:44.220118Z",
      "created_at": "2026-08-11T09:05:44.220118Z"
    }
  ]
}
```

The response has five fields.

| Field | Type | Description |
| --- | --- | --- |
| `total` | `integer` | The total number of interventions recorded under your account, across all pages. |
| `count` | `integer` | The number of interventions actually returned in this page. |
| `skip` | `integer` | The `skip` value applied, exactly as you sent it. |
| `limit` | `integer` | The `limit` value applied, exactly as you sent it. |
| `items` | `array` | The interventions of the page, from the most recent to the oldest. |

Each entry in `items` has twelve fields.

| Field | Type | Description |
| --- | --- | --- |
| `id` | `integer` | The intervention identifier. |
| `product_id` | `integer` | The product this intervention is attached to. |
| `brand_id` | `integer` | The brand this product belongs to. |
| `event_type` | `string` | The intervention type. See the list below. |
| `proof_level` | `string` or `null` | What the author proved at the time of recording. See the list below. |
| `title` | `string` | The label entered when recording. |
| `description` | `string` or `null` | The free-form detail you entered, or `null`. |
| `event_metadata` | `object` or `null` | The additional information recorded with the intervention. See below. |
| `performed_by` | `string` or `null` | The author's display name, followed by their capacity in parentheses. |
| `product_name` | `string` or `null` | The product name at read time. Reads `null` if the product has no name, or if the product row is no longer joined. Do not use it to decide that a product has disappeared. |
| `occurred_at` | `string` | The date of the intervention, in ISO 8601 format with time zone. |
| `created_at` | `string` | The date the record was written, in ISO 8601 format with time zone. |

> [!ATTENTION] The field is called `metadata` when you write and `event_metadata` when you read
> `POST /v1/partner-portal/interventions` expects your additional information
> under the name `metadata`. This list returns it to you under the name
> `event_metadata`. The content is the same. Plan for both names if you write
> and read back in the same code.

`event_type` takes one of the eight values a partner account can record. Four
belong to repair: `repair`, `maintenance`, `reconditioning`,
`after_sale_service`. Four belong to end of life: `recycling`, `end_of_life`,
`destruction`, `return`. A single entry carries only one of these values.

`proof_level` takes one of these values.

| Value | What it means |
| --- | --- |
| `declared` | You entered a product identifier and nothing else. |
| `customer_code` | The customer generated a single-use code and gave it to you. |
| `work_order` | The brand issued a work order naming this product and your account. |
| `null` | We did not ask the question on this record. It predates the existence of proof levels, or it comes from a path other than the partner portal. |

The service writes `proof_level` at creation and never changes it afterward.

`event_metadata` carries the `partner_type` key, which reads `repairer` or
`recycler`, on the interventions recorded from the partner portal. The field
can read `null`, and an older entry may not carry this key. Test for its
presence before reading it.

The other keys are the ones you sent. The partner portal writes
`replaced_parts` and `cost_eur` there for a repair, `recovered_materials` and
`method` for an end-of-life treatment, and `notes` in both cases.

> [!INFO] The filter is on the author of the event
> An event written by the brand from its console, or by another partner, is
> not part of this list. On the other hand, if your account requested a repair
> on a product it owns as a customer, that event also appears in the list,
> with `proof_level` at `null` and no `partner_type` key. A brand with no
> intervention from you returns a 200 with `items` empty and `total` at 0.

## Errors

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

| Code | Condition | What to do |
| --- | --- | --- |
| 401 | No session token accompanies the call, neither in an `Authorization` header nor in a cookie. The response also carries `WWW-Authenticate: Bearer`. | Log in, then send the token you obtain. |
| 401 | A logout or a password change revoked the token. | Log in again to obtain a new token. |
| 401 | The token presented is not a session token. A token awaiting two-factor verification gives the message `MFA verification required`. | Complete the login, including two-factor verification, then use the session token. |
| 401 | The token carries no email address. | Log in again. |
| 401 | The service could not read the token at all. The message is `Invalid JWT token`. | Log in again. If the error comes back, contact support. |
| 401 | The account is no longer active. | Contact the brand that accredited you, or support. |
| 403 | The token is expired, malformed, or its signature does not match. The message is `Token invalide`. | Log in again. Treat this 403 as a session to renew. |
| 403 | The account is neither a repairer account nor a recycler account. | Use the partner account the brand accredited. A brand administrator account does not open this surface. |
| 403 | The call comes from a browser, carries the session cookie and announces neither `Origin` nor `Referer`. | Call from the partner portal, or switch to the `Authorization` header for a server-to-server call. |
| 403 | The call comes from a domain that is not authorized. The message is `Forbidden origin`. | Call from a SealTrust domain, or switch to the `Authorization` header. |
| 404 | The account designated by the token no longer exists. | Log in again. If the account was deleted, ask the brand for a new accreditation. |
| 422 | `skip` is negative, `limit` is below 1 or above 100, or one of the two values is not an integer. `detail` is a list naming the offending parameter. | Fix the value. The upper bound of `limit` is 100. |
| 422 | A pagination value sent is outside the bounds the service accepts. The message is generic and does not name the parameter. The response carries an `X-Request-Id` header. | Reduce `skip`. Normal pagination stays well below this bound. |
| 429 | You exceeded the rate limit. The response carries a `Retry-After` header. | Wait the number of seconds given by `Retry-After`, then retry. The limit covers the whole partner portal, so space out all your calls. |
| 500 | An unexpected error occurred while processing your call. The body reads `{"detail": "Internal Server Error"}` and the response carries an `X-Request-Id` header. | Retry. If the error persists, contact support with the value of `X-Request-Id`. |

This endpoint never returns 404 for an empty history. A partner account that
has recorded nothing yet receives a 200 with `items` empty and `total` at 0.

## See also

- [`POST /partner-portal/interventions`](/en/reference/post-partner-portal-interventions/),
  record an intervention on a product.
- [`GET /partner-portal/products/{identifier}`](/en/reference/get-partner-portal-products/),
  find a product of a brand that accredited you.
- [`GET /partner-portal/me`](/en/reference/get-partner-portal-me/),
  read your partner profile and the brands that accredited you.
