# Cart API Documentation

**Base URL:** `/api/v1`

## Overview

This API provides cart functionality for both authenticated users (via `contact_id`) and guest users (via `guest_token`). The cart system supports simple products and product variants.

---

## Database Schema

### Carts Table

| Column        | Type                 | Description                                                      |
| ------------- | -------------------- | ---------------------------------------------------------------- |
| `id`          | bigint               | Primary key                                                      |
| `uid`         | string               | Unique identifier (unique index)                                 |
| `contact_id`  | bigint (nullable)    | Owner reference (logged-in user)                                 |
| `guest_token` | string (nullable)    | Anonymous session identifier (unique)                            |
| `status`      | enum                 | `active`, `merged`, `abandoned`, `converted` (default: `active`) |
| `coupon_code` | string (nullable)    | Applied coupon code                                              |
| `notes`       | text (nullable)      | Cart-level notes                                                 |
| `expires_at`  | timestamp (nullable) | Cart expiration                                                  |
| `created_at`  | timestamp            | Creation timestamp                                               |
| `updated_at`  | timestamp            | Last update timestamp                                            |

### Cart Items Table

| Column               | Type              | Description                                               |
| -------------------- | ----------------- | --------------------------------------------------------- |
| `id`                 | bigint            | Primary key                                               |
| `cart_id`            | bigint            | Foreign key to `carts`                                    |
| `product_id`         | bigint            | Foreign key to `products`                                 |
| `product_variant_id` | bigint (nullable) | Foreign key to `product_variants` (NULL = simple product) |
| `quantity`           | unsigned integer  | Item quantity (default: 1)                                |
| `notes`              | text (nullable)   | Per-item customer note                                    |
| `created_at`         | timestamp         | Creation timestamp                                        |

---

## Endpoints

### 1. Get Cart

Retrieve the current active cart for a user or guest.

- **Endpoint:** `GET /cart` (auth) or `GET /cart/guest` (guest)
- **Authentication:** Bearer token (auth) or `guest_token` query param (guest)
- **Query Parameters:**
    - `guest_token` (string) - Required for guest carts
    - `contact_id` (integer) - Optional, for authenticated users

**Response:**

```json
{
    "status": "success",
    "data": {
        "id": 1,
        "uid": "cart-uuid-here",
        "user_id": null,
        "guest_token": "abc123xyz",
        "channel": "online",
        "status": "active",
        "coupon_code": null,
        "notes": null,
        "expires_at": "2026-04-01 00:00:00",
        "item_count": 2,
        "total_quantity": 5,
        "items": [
            {
                "id": 10,
                "product_id": 5,
                "product_variant_id": null,
                "quantity": 3,
                "notes": null,
                "product": {
                    "id": 5,
                    "name": "Product Name",
                    "sku": "PROD-001",
                    "slug": "product-name"
                },
                "variant": null,
                "created_at": "2026-03-11 10:00:00"
            },
            {
                "id": 11,
                "product_id": 5,
                "product_variant_id": 12,
                "quantity": 2,
                "notes": "Gift wrap please",
                "product": {
                    "id": 5,
                    "name": "Product Name",
                    "sku": "PROD-001",
                    "slug": "product-name"
                },
                "variant": {
                    "id": 12,
                    "title": "Large / Red",
                    "sku": "PROD-001-L-R"
                },
                "created_at": "2026-03-11 10:05:00"
            }
        ],
        "created_at": "2026-03-11 09:00:00",
        "updated_at": "2026-03-11 10:05:00"
    }
}
```

---

### 2. Add Item to Cart

Add a product (or variant) to cart. Increments quantity if the same product/variant already exists.

- **Endpoint:** `POST /cart/items` (auth) or `POST /cart/guest/items` (guest)
- **Authentication:** Bearer token (auth) or `guest_token` in body (guest)

**Request Body:**

```json
{
    "product_id": 5,
    "product_variant_id": null,
    "quantity": 1,
    "notes": null,
    "guest_token": "abc123xyz"
}
```

| Field                | Type               | Required | Description                           |
| -------------------- | ------------------ | -------- | ------------------------------------- |
| `product_id`         | integer            | Yes      | Product ID to add                     |
| `product_variant_id` | integer (nullable) | No       | Variant ID (NULL for simple products) |
| `quantity`           | integer            | No       | Quantity (default: 1)                 |
| `notes`              | string (nullable)  | No       | Per-item note                         |
| `guest_token`        | string             | No       | Required for guest carts              |

**Response (201 Created):**

```json
{
    "status": "success",
    "message": "Item added to cart.",
    "data": {
        "id": 1,
        "uid": "cart-uuid-here",
        "user_id": null,
        "guest_token": "abc123xyz",
        "channel": "online",
        "status": "active",
        "coupon_code": null,
        "notes": null,
        "expires_at": "2026-04-01 00:00:00",
        "item_count": 1,
        "total_quantity": 1,
        "items": [
            {
                "id": 10,
                "product_id": 5,
                "product_variant_id": null,
                "quantity": 1,
                "notes": null,
                "product": {
                    "id": 5,
                    "name": "Product Name",
                    "sku": "PROD-001",
                    "slug": "product-name"
                },
                "variant": null,
                "created_at": "2026-03-11 10:00:00"
            }
        ],
        "created_at": "2026-03-11 09:00:00",
        "updated_at": "2026-03-11 10:00:00"
    }
}
```

---

### 3. Update Cart Item

Update the quantity of an existing item in the cart.

- **Endpoint:** `PATCH /cart/items/{itemId}` (auth) or `PATCH /cart/guest/items/{itemId}` (guest)
- **Authentication:** Bearer token (auth) or `guest_token` in body (guest)
- **URL Parameters:**
    - `itemId` (integer) - The cart item ID

**Request Body:**

```json
{
    "quantity": 5
}
```

| Field      | Type    | Required | Description           |
| ---------- | ------- | -------- | --------------------- |
| `quantity` | integer | Yes      | New quantity (1-9999) |

**Response:**

```json
{
    "status": "success",
    "message": "Cart item updated.",
    "data": {
        "id": 1,
        "uid": "cart-uuid-here",
        "user_id": null,
        "guest_token": "abc123xyz",
        "channel": "online",
        "status": "active",
        "coupon_code": null,
        "notes": null,
        "expires_at": "2026-04-01 00:00:00",
        "item_count": 1,
        "total_quantity": 5,
        "items": [
            {
                "id": 10,
                "product_id": 5,
                "product_variant_id": null,
                "quantity": 5,
                "notes": null,
                "product": {
                    "id": 5,
                    "name": "Product Name",
                    "sku": "PROD-001",
                    "slug": "product-name"
                },
                "variant": null,
                "created_at": "2026-03-11 10:00:00"
            }
        ],
        "created_at": "2026-03-11 09:00:00",
        "updated_at": "2026-03-11 10:05:00"
    }
}
```

**Error Response (404):**

```json
{
    "status": "error",
    "message": "Cart item not found."
}
```

---

### 4. Remove Item from Cart

Remove a single item from the cart.

- **Endpoint:** `DELETE /cart/items/{itemId}` (auth) or `DELETE /cart/guest/items/{itemId}` (guest)
- **Authentication:** Bearer token (auth) or `guest_token` in body (guest)
- **URL Parameters:**
    - `itemId` (integer) - The cart item ID

**Response:**

```json
{
    "status": "success",
    "message": "Item removed from cart.",
    "data": {
        "id": 1,
        "uid": "cart-uuid-here",
        "user_id": null,
        "guest_token": "abc123xyz",
        "channel": "online",
        "status": "active",
        "coupon_code": null,
        "notes": null,
        "expires_at": "2026-04-01 00:00:00",
        "item_count": 0,
        "total_quantity": 0,
        "items": [],
        "created_at": "2026-03-11 09:00:00",
        "updated_at": "2026-03-11 10:10:00"
    }
}
```

---

### 5. Clear Cart

Remove all items from the cart.

- **Endpoint:** `DELETE /cart` (auth) or `DELETE /cart/guest` (guest)
- **Authentication:** Bearer token (auth) or `guest_token` in body (guest)

**Response:**

```json
{
    "status": "success",
    "message": "Cart cleared.",
    "data": {
        "id": 1,
        "uid": "cart-uuid-here",
        "user_id": null,
        "guest_token": "abc123xyz",
        "channel": "online",
        "status": "active",
        "coupon_code": null,
        "notes": null,
        "expires_at": "2026-04-01 00:00:00",
        "item_count": 0,
        "total_quantity": 0,
        "items": [],
        "created_at": "2026-03-11 09:00:00",
        "updated_at": "2026-03-11 10:15:00"
    }
}
```

---

### 6. Merge Guest Cart (Authenticated Users Only)

Merge guest cart into user cart after login.

- **Endpoint:** `POST /cart/merge`
- **Authentication:** Bearer token required

**Request Body:**

```json
{
    "guest_token": "abc123xyz",
    "contact_id": 1
}
```

| Field         | Type    | Required | Description                   |
| ------------- | ------- | -------- | ----------------------------- |
| `guest_token` | string  | Yes      | Guest cart token to merge     |
| `contact_id`  | integer | Yes      | User/contact ID to merge into |

**Response:**

```json
{
    "status": "success",
    "message": "Guest cart merged.",
    "data": {
        "id": 2,
        "uid": "cart-uuid-merged",
        "user_id": 1,
        "guest_token": null,
        "channel": "online",
        "status": "active",
        "coupon_code": null,
        "notes": null,
        "expires_at": "2026-04-01 00:00:00",
        "item_count": 3,
        "total_quantity": 7,
        "items": [
            {
                "id": 20,
                "product_id": 5,
                "product_variant_id": null,
                "quantity": 4,
                "notes": null,
                "product": {
                    "id": 5,
                    "name": "Product Name",
                    "sku": "PROD-001",
                    "slug": "product-name"
                },
                "variant": null,
                "created_at": "2026-03-11 09:00:00"
            },
            {
                "id": 21,
                "product_id": 8,
                "product_variant_id": 15,
                "quantity": 3,
                "notes": "Fragile",
                "product": {
                    "id": 8,
                    "name": "Another Product",
                    "sku": "PROD-002",
                    "slug": "another-product"
                },
                "variant": {
                    "id": 15,
                    "title": "Medium / Blue",
                    "sku": "PROD-002-M-B"
                },
                "created_at": "2026-03-11 09:30:00"
            }
        ],
        "created_at": "2026-03-11 08:00:00",
        "updated_at": "2026-03-11 10:20:00"
    }
}
```

---

## Cart Status Values

| Status      | Description                      |
| ----------- | -------------------------------- |
| `active`    | Cart is currently in use         |
| `merged`    | Guest cart merged into user cart |
| `abandoned` | Cart was abandoned               |
| `converted` | Cart converted to order          |

---

## Error Responses

| HTTP Code | Description         |
| --------- | ------------------- |
| 404       | Cart item not found |
| 422       | Validation error    |
| 500       | Server error        |

**Error Response Format:**

```json
{
    "status": "error",
    "message": "Error description here."
}
```

---

## Notes

- **Guest carts:** Use `guest_token` parameter in all requests
- **Authenticated carts:** Use Bearer token; optionally pass `contact_id`
- **Product variants:** `product_variant_id` is NULL for simple products
- **Duplicate items:** Adding the same product/variant combination increments quantity
- **Relations:** The `product` and `variant` objects are included when loaded
