# Cart API Documentation

## Overview

The Cart API provides endpoints for managing shopping carts in the Missio Shop Module. It supports both guest checkout (via `cart_token`) and authenticated customer carts, with features for adding/updating items with product variants and calculating totals.

**Key Features:**
- Guest checkout support via `cart_token` parameter
- Product variant selection using attributes
- Automatic variant matching based on attribute combinations
- Business rule enforcement (missio_owned, recurring products)
- Real-time cart totals calculation
- Multiple image sizes for products (sm, md, lg, original)

## Base URL

```
https://adminv2.missio.io/api/catalog
```

## Authentication

**Required Header:**
- `X-Company-Hash`: Company identifier (required for all requests)

**Optional Header:**
- `Authorization: Bearer {token}`: For authenticated customer carts (links cart to customer account)

**Guest Checkout:**
- Use `cart_token` parameter in requests to maintain cart across sessions
- First request generates a `cart_token` - store and use in subsequent requests
- No authentication required for guest checkout

## Endpoints

### 1. Get Cart

Retrieve current cart with items and totals, or create new empty cart if none exists.

**Endpoint:** `GET /cart`

**Headers:**
```
X-Company-Hash: your-company-hash
Authorization: Bearer {token}  (optional - for authenticated customers)
```

**Query Parameters:**
- `cart_token` (optional): Cart token for guest checkout

**Example Request:**
```bash
curl -X GET "https://adminv2.missio.io/api/catalog/cart?cart_token=abc123" \
  -H "X-Company-Hash: your-company-hash"
```

**Response (200 OK) - Empty Cart:**
```json
{
  "status": "success",
  "message": "Cart is empty",
  "cart_token": "cc9683822658df7eabf0c6800d5a17a2",
  "customer_id": null,
  "items": [],
  "totals": {
    "subtotal": "0.00",
    "discount": "0.00",
    "tax": "0.00",
    "shipping": "0.00",
    "total": "0.00",
    "items_count": 0
  }
}
```

**Response (200 OK) - Cart With Items:**
```json
{
  "status": "success",
  "message": "Cart retrieved successfully",
  "cart_token": "5f8a9b7c6d5e4f3g2h1i",
  "customer_id": 123,
  "items": [
    {
      "id": 456,
      "product_id": 1008,
      "variant_id": 201,
      "name": "Blue T-Shirt - Large",
      "sku": "TSHIRT-BLUE-L",
      "quantity": 2,
      "unit_price": "29.99",
      "amount": "59.98",
      "attributes": {
        "19": "674",
        "20": "1136"
      },
      "image": {
        "sm": "https://missiov2.s3.us-east-2.amazonaws.com/1/products/1008/sm_product-image.jpg",
        "md": "https://missiov2.s3.us-east-2.amazonaws.com/1/products/1008/md_product-image.jpg",
        "lg": "https://missiov2.s3.us-east-2.amazonaws.com/1/products/1008/lg_product-image.jpg",
        "original": "https://missiov2.s3.us-east-2.amazonaws.com/1/products/1008/product-image.jpg"
      }
    }
  ],
  "coupon_code": null,
  "totals": {
    "subtotal": "59.98",
    "discount": "0.00",
    "tax": "0.00",
    "shipping": "0.00",
    "total": "59.98",
    "items_count": 2
  }
}
```

---

### 2. Add Item to Cart

Add a product to cart or update quantity if item already exists.

**Endpoint:** `POST /cart/items`

**Headers:**
```
X-Company-Hash: your-company-hash
Content-Type: application/json
Authorization: Bearer {token}  (optional)
```

**Request Body:**
```json
{
  "product_id": 990,
  "attributes": {
    "19": "674",
    "20": "1136"
  },
  "quantity": 2,
  "cart_token": "cc9683822658df7eabf0c6800d5a17a2"
}
```

**Parameters:**
- `product_id` (required): Product ID
- `attributes` (optional): Object mapping attribute IDs to value IDs for variant selection
- `quantity` (optional): Quantity to add (default: 1). If item exists and quantity provided, sets to this quantity. If item exists and no quantity provided, increments by 1.
- `cart_token` (optional): Cart token for guest checkout

**Variant Matching:**
The API automatically finds the matching product variant based on the provided attributes. For example:
- Attribute 19 (Size) = 674 (Large)
- Attribute 20 (Color) = 1136 (Blue)

If a matching variant is found, the cart item will use the variant's price, SKU, and name.

**Business Rules:**
1. **Missio Owned Products:** Cannot mix missio_owned products with regular products in same cart
2. **Recurring Products:** Cannot mix recurring products with one-time payment products
3. **Duplicate Detection:** Items with same product_id + attributes are treated as duplicates

**Example Request:**
```bash
curl -X POST "https://adminv2.missio.io/api/catalog/cart/items" \
  -H "X-Company-Hash: your-company-hash" \
  -H "Content-Type: application/json" \
  -d '{
    "product_id": 990,
    "attributes": {
      "19": "674",
      "20": "1136"
    },
    "quantity": 2,
    "cart_token": "abc123"
  }'
```

**Response (200 OK):**
```json
{
  "status": "success",
  "message": "Item added to cart successfully",
  "cart_token": "5f8a9b7c6d5e4f3g2h1i",
  "item": {
    "id": 789,
    "product_id": 990,
    "variant_id": 201,
    "name": "Product Name - Variant Name",
    "sku": "PROD-VAR-SKU",
    "quantity": 2,
    "unit_price": "29.99",
    "amount": "59.98",
    "attributes": {
      "19": "674",
      "20": "1136"
    },
    "image": {
      "sm": "https://missiov2.s3.us-east-2.amazonaws.com/1/products/990/sm_image.jpg",
      "md": "https://missiov2.s3.us-east-2.amazonaws.com/1/products/990/md_image.jpg",
      "lg": "https://missiov2.s3.us-east-2.amazonaws.com/1/products/990/lg_image.jpg",
      "original": "https://missiov2.s3.us-east-2.amazonaws.com/1/products/990/image.jpg"
    }
  },
  "totals": {
    "subtotal": "59.98",
    "discount": "0.00",
    "tax": "0.00",
    "shipping": "0.00",
    "total": "59.98",
    "items_count": 2
  }
}
```

**Error Response (400) - Business Rule Violation:**
```json
{
  "status": "error",
  "message": "Missio owned item already in cart. You can not add other products."
}
```

**Error Response (422) - Validation Error:**
```json
{
  "status": "error",
  "message": "Validation failed",
  "errors": {
    "product_id": ["The product id field is required."]
  }
}
```

---

### 3. Remove Item from Cart

Remove a specific item from cart or clear entire cart.

**Endpoint:** `DELETE /cart/items/{id}`

**Headers:**
```
X-Company-Hash: your-company-hash
Authorization: Bearer {token}  (optional)
```

**Path Parameters:**
- `id`: Cart item ID, or use `all` to clear entire cart

**Query Parameters:**
- `cart_token` (optional): Cart token for guest checkout

**Example Request - Remove Specific Item:**
```bash
curl -X DELETE "https://adminv2.missio.io/api/catalog/cart/items/456?cart_token=abc123" \
  -H "X-Company-Hash: your-company-hash"
```

**Example Request - Clear Cart:**
```bash
curl -X DELETE "https://adminv2.missio.io/api/catalog/cart/items/all?cart_token=abc123" \
  -H "X-Company-Hash: your-company-hash"
```

**Response (200 OK):**
```json
{
  "status": "success",
  "message": "Item removed from cart successfully",
  "totals": {
    "subtotal": "29.99",
    "discount": "0.00",
    "tax": "0.00",
    "shipping": "0.00",
    "total": "29.99",
    "items_count": 1
  }
}
```

**Response (200 OK) - Clear All:**
```json
{
  "status": "success",
  "message": "Cart cleared successfully",
  "totals": {
    "subtotal": "0.00",
    "discount": "0.00",
    "tax": "0.00",
    "shipping": "0.00",
    "total": "0.00",
    "items_count": 0
  }
}
```

**Error Response (404):**
```json
{
  "status": "error",
  "message": "Cart item not found"
}
```
---

## Guest Checkout Flow

### How cart_token Works

For guest (unauthenticated) users:

1. **First Request:** Call GET /cart without cart_token
   - API generates new `cart_token` 
   - Returns in response
   
2. **Store Token:** Save `cart_token` in localStorage/sessionStorage

3. **Subsequent Requests:** Include cart_token in all requests
   - Query parameter for GET/DELETE: `?cart_token=abc123`
   - Request body for POST: `{"cart_token": "abc123", ...}`

4. **Token Persistence:** Use same token across app restarts

---

## Response Format

All responses follow this structure:

### Success Response
```json
{
  "status": "success",
  "message": "Operation description",
  "cart_token": "abc123",
  "customer_id": null,
  "items": [...],
  "totals": {...}
}
```

### Error Response
```json
{
  "status": "error",
  "message": "Error description",
  "errors": {
    "field": ["Validation message"]
  }
}
```

### Cart Item Object
```json
{
  "id": 456,
  "product_id": 990,
  "variant_id": 201,
  "name": "Product Name",
  "sku": "PROD-SKU",
  "quantity": 2,
  "unit_price": "29.99",
  "amount": "59.98",
  "attributes": {
    "19": "674",
    "20": "1136"
  },
  "image": {
    "sm": "url_to_small_image",
    "md": "url_to_medium_image", 
    "lg": "url_to_large_image",
    "original": "url_to_original_image"
  }
}
```

### Totals Object
```json
{
  "subtotal": "59.98",
  "discount": "0.00",
  "tax": "0.00",
  "shipping": "0.00",
  "total": "59.98",
  "items_count": 2
}
```

---

## Business Rules

### Product Restrictions

**Missio Owned Products:**
- Cannot mix missio_owned with regular products
- If cart has missio_owned item, only other missio_owned items can be added
- If cart has regular items, missio_owned items cannot be added

**Recurring Products:**
- Cannot mix recurring with one-time products
- If cart has recurring item, only other recurring items allowed
- If cart has one-time items, recurring items blocked

### Variant Matching

Variants are matched using ALL provided attributes:

**Example Database:**
```
Variant 1: Size=Large (19:674), Color=Blue (20:1136)
Variant 2: Size=Large (19:674), Color=Red (20:1137)
```

**Request:**
```json
{
  "attributes": {
    "19": "674",
    "20": "1136"
  }
}
```
✅ Matches Variant 1

**Partial Match:**
```json
{
  "attributes": {
    "19": "674"
  }
}
```
❌ No match (must provide ALL attributes)

---

## Error Handling

### HTTP Status Codes

- `200 OK`: Success
- `400 Bad Request`: Business rule violation
- `404 Not Found`: Resource not found
- `422 Unprocessable Entity`: Validation error

### Common Errors

| Error Message | Cause | Solution |
|--------------|-------|----------|
| Invalid company identifier | Missing/invalid X-Company-Hash | Verify company hash |
| Cart not found | Invalid cart_token | Get new cart_token |
| Cart item not found | Invalid item ID | Refresh cart |
| Product not found | Invalid product_id | Check product exists |
| Missio owned item already in cart | Business rule | Clear cart first |
| Recurring item already in cart | Business rule | Clear cart first |
| Validation failed | Missing/invalid fields | Check request format |

---

## Postman Collection

Import the Missio Shop API collection:

```
postman/Missio-Shop-API.postman_collection.json
```

**Environment Variables:**
- `base_url`: https://adminv2.missio.io
- `c_hash`: Your company hash

**Available Requests:**
1. Get Cart
2. Add Item to Cart
3. Remove Cart Item

---

## Related Documentation

- [API Quick Start](API_QUICK_START.md) - Getting started
- [Catalog API](CATALOG_API.md) - Product browsing
- [API Documentation](API_DOCUMENTATION.md) - Authentication

---

## Changelog

### Version 2.0 (Current)

**Changed:**
- Removed `updateItem` endpoint (use addItem with quantity instead)
- Removed `applyCoupon` endpoint (moved to payment controller)
- Removed `removeCoupon` endpoint (moved to payment controller)
- Removed `totals` endpoint (totals included in cart response)
- Changed from `cart_id` to `cart_token` in responses
- Added guest checkout support via `cart_token` parameter

**Features:**
- ✅ Guest checkout with cart_token
- ✅ Authenticated customer carts
- ✅ Product variant selection via attributes
- ✅ Automatic variant matching
- ✅ Business rule enforcement
- ✅ Multiple image sizes
- ✅ Real-time totals calculation
