Carts & Checkout
Claiming a cart
Attach a guest cart to a logged-in customer, merging any existing cart the customer already had.
View as MarkdownA visitor typically builds a cart anonymously and only logs in later. Claiming binds that anonymous cart to the logged-in customer identified by X-Customer-Token. From then on, the cart is customer-owned: requests against it must carry the owner's token (see the ownership rules on the Carts page), prices resolve in the customer's pricing context, and checkout binds the order to the customer.
A visitor typically builds a cart anonymously and only logs in later. Claiming binds that anonymous cart to the logged-in customer identified by X-Customer-Token. From then on, the cart is customer-owned: requests against it must carry the owner's token (see the ownership rules on the Carts page), prices resolve in the customer's pricing context, and checkout binds the order to the customer.
Merge behavior
If the customer already had another active cart, its lines are folded into the claimed cart:
- Lines dedupe on the combination of product, variant, and configuration: matching lines have their quantities summed, then clamped to the policy's
max_quantity_per_line. - Extra distinct lines from the old cart are dropped once the claimed cart reaches
max_lines. - The old cart's status becomes
mergedand its stock holds are released. A merged cart id keeps working onGET /carts/{id}but returns 404 on writes.
Claiming a cart that already belongs to this same customer is a no-op and returns the cart unchanged. Claiming a cart that belongs to a different customer fails with 403.
Note that a cart bound to a guest customer row via email capture (PATCH /carts/{id} with email) has customer_id set too: claiming it succeeds only when the token resolves to that same customer; otherwise it is the 403 case.
Merge behavior
If the customer already had another active cart, its lines are folded into the claimed cart:
- Lines dedupe on the combination of product, variant, and configuration: matching lines have their quantities summed, then clamped to the policy's
max_quantity_per_line. - Extra distinct lines from the old cart are dropped once the claimed cart reaches
max_lines. - The old cart's status becomes
mergedand its stock holds are released. A merged cart id keeps working onGET /carts/{id}but returns 404 on writes.
Claiming a cart that already belongs to this same customer is a no-op and returns the cart unchanged. Claiming a cart that belongs to a different customer fails with 403.
Note that a cart bound to a guest customer row via email capture (PATCH /carts/{id} with email) has customer_id set too: claiming it succeeds only when the token resolves to that same customer; otherwise it is the 403 case.
POST /v1/api/commerce/carts/{id}/claim
Requires commerce:write and an active cart. X-Customer-Token is mandatory: without a resolvable token the request fails with status 401 and an empty body. No request body. Returns the full cart envelope, the same shape as GET /v1/api/commerce/carts/{id}, now including any merged-in lines, with status 200.
Parameters
Path
| Name | Type | Required | Description |
|---|---|---|---|
id | string (UUID) | yes | Cart id. Must be an active cart. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
X-Customer-Token | string | yes | Customer session token. Must resolve to a customer, else 401. |
No body.
Errors
| Status | Body | When |
|---|---|---|
| 401 | empty body | X-Customer-Token missing or unresolvable, or the customers module is unavailable. |
| 403 | empty body | The cart is already bound to a different customer. |
| 404 | {"message": "..."} | Cart unknown, expired, or not active. |
| 403 | scope, module, or suspension body | See the Carts page. |
| 429 | {"message": "Too Many Attempts."} | Rate limit exceeded. |
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}"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();{
"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}"
}
}POST /v1/api/commerce/carts/{id}/claim
Requires commerce:write and an active cart. X-Customer-Token is mandatory: without a resolvable token the request fails with status 401 and an empty body. No request body. Returns the full cart envelope, the same shape as GET /v1/api/commerce/carts/{id}, now including any merged-in lines, with status 200.
Parameters
Path
| Name | Type | Required | Description |
|---|---|---|---|
id | string (UUID) | yes | Cart id. Must be an active cart. |
Headers
| Name | Type | Required | Description |
|---|---|---|---|
X-Customer-Token | string | yes | Customer session token. Must resolve to a customer, else 401. |
No body.
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}"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();{
"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}"
}
}Errors
| Status | Body | When |
|---|---|---|
| 401 | empty body | X-Customer-Token missing or unresolvable, or the customers module is unavailable. |
| 403 | empty body | The cart is already bound to a different customer. |
| 404 | {"message": "..."} | Cart unknown, expired, or not active. |
| 403 | scope, module, or suspension body | See the Carts page. |
| 429 | {"message": "Too Many Attempts."} | Rate limit exceeded. |