# Een cart claimen

Een bezoeker bouwt een cart doorgaans anoniem op en logt pas later in. Claimen koppelt die anonieme cart aan de ingelogde klant die door `X-Customer-Token` wordt geïdentificeerd. Vanaf dat moment is de cart klanteigendom: requests erop moeten het token van de eigenaar meesturen (zie de eigenaarschapsregels op de pagina Carts), prijzen worden bepaald in de pricingcontext van de klant, en checkout koppelt de order aan de klant.

## Samenvoeggedrag

Als de klant al andere `active` carts had, wordt elk daarvan in de geclaimde cart gevouwen:

- Regels dedupliceren op de combinatie van product, variant en configuratie: van overeenkomende regels worden de hoeveelheden opgeteld en vervolgens begrensd op `max_quantity_per_line` uit de policy.
- Extra afzonderlijke regels uit de oude cart vervallen zodra de geclaimde cart `max_lines` bereikt.
- De geclaimde cart behoudt zijn eigen `email` en `metadata` als die gezet zijn; is een van beide null, dan neemt hij de waarde van de oude cart over.
- De status van elke oude cart wordt `merged` en zijn voorraadreserveringen worden vrijgegeven. Een merged cart-id blijft werken op `GET /carts/{id}` maar geeft een 404 op schrijfacties.

Een cart claimen die al aan dezelfde klant toebehoort is een no-op en geeft de cart ongewijzigd terug. Een cart claimen die aan een andere klant toebehoort faalt met een 403.

Let op: een cart die via e-mailregistratie aan een guest-klantrij is gebonden (`PATCH /carts/{id}` met `email`) heeft ook `customer_id` gezet: die claimen slaagt alleen wanneer het token naar diezelfde klant herleidt; anders geldt het 403-geval.

## POST /v1/api/commerce/carts/{id}/claim

Vereist `commerce:write` en een `active` cart. `X-Customer-Token` is verplicht: zonder een herleidbaar token faalt de request met status 401 en een lege body. Geen request body. Geeft de volledige cart-envelope terug, dezelfde vorm als `GET /v1/api/commerce/carts/{id}`, nu inclusief eventueel samengevoegde regels, met status 200.

### Parameters

**Pad**

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `id` | string (UUID) | ja | Cart-id. Moet een `active` cart zijn. |

**Headers**

| Naam | Type | Verplicht | Beschrijving |
| --- | --- | --- | --- |
| `X-Customer-Token` | string | ja | Klantsessietoken. Moet naar een klant herleiden, anders 401. |

Geen body.

```bash title="Request"
curl -X POST https://api.borkol.com/v1/api/commerce/carts/9d3f2a10-6b7c-4e6d-9f21-8a54c1d2e3f4/claim \
  -H "Authorization: Bearer {api_key}" \
  -H "X-Customer-Token: {customer_token}"
```

```javascript title="Request (JS)"
const res = await fetch(
  `https://api.borkol.com/v1/api/commerce/carts/${cartId}/claim`,
  {
    method: "POST",
    headers: {
      Authorization: `Bearer ${apiKey}`,
      "X-Customer-Token": customerToken,
    },
  }
);
const { data: cart } = await res.json();
```

```json title="Response"
{
  "data": {
    "id": "9d3f2a10-6b7c-4e6d-9f21-8a54c1d2e3f4",
    "status": "active",
    "lines": [
      { "id": "5e6f7a8b-...", "quantity": 3, "...": "..." },
      { "id": "6f7a8b9c-...", "quantity": 1, "...": "merged in from the customer's previous cart" }
    ],
    "...": "same cart shape as GET /v1/api/commerce/carts/{id}"
  }
}
```

### Fouten

| Status | Body | Wanneer |
| --- | --- | --- |
| 401 | lege body | `X-Customer-Token` ontbreekt of is niet herleidbaar, of de customers-module is niet beschikbaar. |
| 403 | lege body | De cart is al gebonden aan een andere klant. |
| 404 | `{"message": "..."}` | Cart onbekend, verlopen of niet `active`. |
| 403 | scope-, module- of schorsingsbody | Zie de pagina Carts. |
| 429 | `{"message": "Too Many Attempts."}` | Rate limit overschreden. |
