> ## Documentation Index
> Fetch the complete documentation index at: https://www.commercengine.io/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Cart

> The Carts module provides the APIs to manage a user's shopping cart. It allows you to add, update, and remove items, apply discounts and loyalty points, manage fulfillment options, and retrieve the cart's state before checkout. Commerce Engine carts are persistent and associated with the user (anonymous or logged-in), enabling seamless experiences across sessions or devices.

**Key Features Covered:**

* **Explicit Cart Creation:** Carts must be created before items can be added.
* **Persistent Carts:** Carts are tied to the user.
* **Item Management:** Add, update quantity, or remove products and variants *to an existing cart*.
* **Pricing Calculation:** Automatically calculates subtotals, taxes, shipping, and grand totals.
* **Discount Application:** Apply coupon codes, automatic promotions, loyalty points, and store credit.
* **Address Management:** Set billing and shipping addresses for checkout calculation.
* **Fulfillment Options:** Fetch fulfillment options and update fulfillment preferences per shipment.
* **User Association:** Carts link to anonymous or logged-in users; retrievable via `user_id` for both.

## Core Concepts

<AccordionGroup>
  <Accordion title="Cart Lifecycle & Persistence">
    * **Creation:** A cart **must always be explicitly created** using `POST /carts` *before* any items can be added. This endpoint requires at least one item to be included in the request body for successful cart creation. There is no concept of creating an empty cart via the API initially.
    * **Association:** Every cart is linked to a user automatically upon creation.
    * **Retrieval:** You can retrieve a specific cart using its `id` (`GET /carts/{id}`) or retrieve the active cart associated with a user (both anonymous and logged-in) via their `user_id` (`GET /carts/users/{user_id}`). This allows fetching the correct cart even if the client loses the `cart_id` but still has the user's token/ID.
    * **Persistence:** Carts persist across sessions as long as the user context (`user_id`) remains the same.
    * **Expiration:** Carts have an `expires_at` timestamp. Inactive carts may be cleaned up after this time. Active interaction typically extends the expiry.
    * **Transition to Order:** The final state of the cart (identified by its `id`) is used as the basis for creating an order via the `POST /orders` endpoint.
  </Accordion>

  <Accordion title="Cart inheritance and merging upon login">
    -When an anonymous user creates a cart and then goes on to login, if the user happens to be a returning user, the currently active cart is merged into the logged in user's ID. This ensures seamless checkout experience.
    -Note that if the logged in user already had a different cart associated from a previous session, that cart will be marked as inactive when they login with an active cart. This is to prevent cart/item conflicts or items suddenly appearing/disappearing from the user's cart.
  </Accordion>

  <Accordion title="Cart Structure (Cart Object)">
    * `id`: The unique identifier for this cart.

    * `active`: Boolean indicating if the cart is still active.

    * `cart_items`: An array of `CartItem` objects detailing each product/variant in the cart.

    * `cart_items_count`: Total number of unique line items.

    * **Pricing Summary:**
      * `subtotal`: Sum of item selling prices (before tax and discounts).
      * `items_tax_amount`: Total tax calculated on items.
      * `subtotal_including_tax`: Subtotal + Item Tax.
      * `shipping_amount`: Calculated shipping cost (before tax).
      * `shipping_tax_amount`: Tax on shipping.
      * `shipping_amount_including_tax`: Shipping + Shipping Tax.
      * `total_tax`: `items_tax_amount` + `shipping_tax_amount` + `handling_charge_tax_amount`.
      * `grand_total`: The final amount after all deductions, including taxes but before loyalty points are redeemed.

    * **Discounts & Redemptions:**
      * `is_promotion_applied`, `promotion_discount_amount`: For automatic promotions.
      * `is_coupon_applied`, `coupon_code`, `coupon_discount_amount`: For user-applied coupons.
      * `loyalty_points_redeemed`: Points applied as discount.
      * `loyalty_points_earned`: Points the user *will* earn if this cart becomes an order.
      * `credit_balance_used`: Store credit/wallet balance applied.
      * `to_be_paid`: **The amount to display at checkout.** This is what the customer actually pays (`grand_total` - `loyalty_points_redeemed_value` - `credit_balance_used`). Always display `to_be_paid` rather than `grand_total` as the final price — it accounts for loyalty points and credit balance deductions.

    * **Addresses:**
      * `billing_address`: `CustomerAddress` object.
      * `shipping_address`: `CustomerAddress` object.
      * `customer_email`, `customer_phone`, `customer_note`: User details associated with the cart.
      * `currency`: Currency details (`code`, `symbol`, `name`).
      * `metadata`: Custom key-value pairs.
      * `expires_at`: Timestamp when the cart might expire if inactive.
  </Accordion>

  <Accordion title="Cart Items (CartItem Object)">
    * `product_id`, `variant_id`, `sku`: Identifiers for the item.
    * `product_name`, `variant_name`, `product_image_url`: Display details.
    * `quantity`: The number of this item in the cart.
    * `stock_available`, `on_offer`, `on_promotion`, `on_subscription`: Status flags.
    * `listing_price`, `selling_price`: Per-unit prices.
    * `promotion_discount_amount`, `coupon_discount_amount`: Discounts applied *to this line item*.
    * `tax_type`, `tax_rate`, `tax_amount`: Tax details for this line item.
    * `shipping_additional_cost`: Any per-item shipping surcharge.
    * `associated_options`: Details of selected variant options (e.g., Color: Red, Size: Large).
    * `subscriptions`: Details if this item is being added as part of a subscription plan.
    * `is_free_item`, `free_quantity`: Indicates if quantity is part of a "free goods" promotion.
  </Accordion>
</AccordionGroup>

## Cart API Endpoints

<AccordionGroup>
  <Accordion title="POST /carts">
    **Explicitly creates a new cart.** This endpoint **requires** at least one item in the `items` array to successfully create the cart. It cannot be used to create an empty cart. This is typically the first cart-related call when a user adds their initial item.

    * **Authentication:** Bearer Token (Anonymous or Logged-in)

    * **Request Body (Required):** *(See `UpdateCartItem` schema)*

      ```json Create Cart Request Body theme={"theme":{"light":"github-light","dark":"github-dark"}}
      {
        "items": [
          {
            "product_id": "PROD_ID_1",
            "variant_id": "VARIANT_ID_A", // or null if no variants
            "quantity": 1
          }
          // Potentially more items
        ]
      }
      ```

    * **Response:** `200 OK` with the newly created `Cart` object, including its unique `id`. Store this `id` for subsequent cart operations.
  </Accordion>

  <Accordion title="GET /carts/{id}">
    Fetches the details of a specific cart using its ID.

    * **Authentication:** Bearer Token (Must match the user associated with the cart ID)
    * **Path Parameter:** `id` (Cart ID obtained from `POST /carts` or a previous cart state)
    * **Response:** `200 OK` with the `Cart` object, or `404 Not Found`.
  </Accordion>

  <Accordion title="DELETE /carts/{id}">
    Removes all items from the specified cart, effectively emptying it but leaving the cart shell intact until expiration/cleanup.

    * **Authentication:** Bearer Token (Must match the user associated with the cart ID)
    * **Path Parameter:** `id` (Cart ID)
    * **Response:** `200 OK` with success message, or `404 Not Found`.
  </Accordion>

  <Accordion title="GET /carts/users/{user_id}">
    Fetches the active cart associated with a specific user ID. **This works for both anonymous and logged-in users.** Use the `user_id` from the user object obtained via `/auth/anonymous` or login flows.

    * **Authentication:** Bearer Token (Token must correspond to the user session associated with `{user_id}`)
    * **Path Parameter:** `user_id`
    * **Response:** `200 OK` with the `Cart` object, or `404 Not Found` if no active cart exists for the user.
  </Accordion>

  <Accordion title="DELETE /carts/users/{user_id}">
    Removes all items from the active cart associated with the specified user ID (anonymous or logged-in).

    * **Authentication:** Bearer Token (Token must correspond to the user session associated with `{user_id}`)
    * **Path Parameter:** `user_id`
    * **Response:** `200 OK` with success message, or `404 Not Found`.
  </Accordion>

  <Accordion title="POST /carts/{id}/items">
    Updates the contents of an **existing cart**. This endpoint **cannot** create a cart; use `POST /carts` for initial creation.

    * **Authentication:** Bearer Token (Must match the user associated with the cart ID)
    * **Path Parameter:** `id` (**Required** Cart ID obtained from `POST /carts` or `GET` requests)
    * **Request Body:** `UpdateCartItem` schema:
      * `product_id`: Required ID of the product.
      * `variant_id`: Required ID of the variant (use `null` if the product has no variants).
      * `quantity`: The desired **total** quantity for this item in the cart.
        * `quantity > 0`: Adds or updates the item to this quantity.
        * `quantity = 0`: **Removes** the item from the cart.
    * **Response:** `200 OK` with the updated `Cart` object reflecting the changes and recalculated totals. Returns `400 Bad Request` if quantity exceeds stock or validation fails, or `404 Not Found` if the Cart ID is invalid.

      ```json Add/Update/Remove Item Request Body theme={"theme":{"light":"github-light","dark":"github-dark"}}
      {
          "product_id": "PROD_ID_B",
          "variant_id": null,
          "quantity": 2 // Set to 0 to remove
      }
      ```
  </Accordion>

  <Accordion title="POST /carts/{id}/address">
    Sets or updates the billing and shipping addresses for the cart. Crucial for calculating shipping costs and taxes.

    * **Authentication:** Bearer Token
    * **Path Parameter:** `id` (Cart ID)
    * **Request Body:** `oneOf` saved address IDs (logged-in users) or full `CustomerAddress` objects (guests or new address). *(Schema details unchanged)*
    * **Response:** `200 OK` with the updated `Cart` object.
  </Accordion>

  <Accordion title="POST /carts/{id}/coupon">
    Applies a coupon code to the cart.

    * **Authentication:** Bearer Token
    * **Path Parameter:** `id` (Cart ID)
    * **Request Body:**
      ```json Apply Coupon Request Body theme={"theme":{"light":"github-light","dark":"github-dark"}}
      { "coupon_code": "YOUR_COUPON_CODE" }
      ```
    * **Response:** `200 OK` with the updated `Cart` object, or `400 Bad Request`.

    <Info>
      **Important Note**

      If a coupon has rules like "valid for first-time customers only," attempting to apply it while the user is anonymous *may* result in a `400 Bad Request` error, potentially with a message indicating login is required. Consider prompting users to log in before applying coupons with such restrictions.
    </Info>
  </Accordion>

  <Accordion title="DELETE /carts/{id}/coupon">
    Removes any currently applied coupon from the cart.

    * **Authentication:** Bearer Token
    * **Path Parameter:** `id` (Cart ID)
    * **Response:** `200 OK` with the updated `Cart` object.
  </Accordion>

  <Accordion title="Redeem/Remove Loyalty Points & Credit Balance">
    *(Endpoints `POST /carts/{id}/loyalty-points`, `DELETE /carts/{id}/loyalty-points`, `POST /carts/{id}/credit-balance`, `DELETE /carts/{id}/credit-balance` remain functionally the same, requiring a **logged-in user's** token.)*
  </Accordion>

  <Accordion title="Wishlist Endpoints">
    *(Endpoints `GET /wishlist/{user_id}`, `POST /wishlist/{user_id}`, `DELETE /wishlist/{user_id}` remain functionally the same, requiring a **logged-in user's** token.)*
  </Accordion>
</AccordionGroup>

## Common Use Cases & Flows

<AccordionGroup>
  <Accordion title="Adding the First Item to the Cart">
    <Frame>
      <iframe title="Adding the First Item to the Cart" allowfullscreen width="100%" height="350" src="https://mermaid.tarkai.dev/embed?definition=sequenceDiagram%0A%20%20%20%20participant%20ClientApp%20as%20Client%20Application%0A%20%20%20%20participant%20User%0A%20%20%20%20participant%20CE_API%20as%20CE%20API%0A%0A%20%20%20%20User-%3E%3EClientApp%3A%20Clicks%20%22Add%20to%20Cart%22%20for%20Product%20A%20(Variant%20X)%0A%20%20%20%20ClientApp-%3E%3ECE_API%3A%20POST%20%2Fcarts%20(Body%3A%20%7Bitems%3A%20%5B%7Bproduct_id%3A%20A%2C%20variant_id%3A%20X%2C%20quantity%3A%201%7D%5D%7D)%0A%20%20%20%20activate%20CE_API%0A%20%20%20%20CE_API--%3E%3EClientApp%3A%20200%20OK%20(Response%3A%20New%20Cart%20Object%20with%20id%3D'cart123'%2C%20contains%20Item%20A)%0A%20%20%20%20deactivate%20CE_API%0A%20%20%20%20ClientApp-%3E%3EClientApp%3A%20Store%20Cart%20ID%20'cart123'.%0A%20%20%20%20ClientApp-%3E%3EClientApp%3A%20Update%20cart%20UI%20(e.g.%2C%20mini-cart%20count%20to%201)" />
    </Frame>
  </Accordion>

  <Accordion title="Adding Subsequent Items / Updating Quantity / Removing">
    <Frame>
      <iframe title="Adding Subsequent Items / Updating Quantity / Removing" allowfullscreen width="100%" height="800" src="https://mermaid.tarkai.dev/embed?definition=sequenceDiagram%0A%20%20%20%20participant%20ClientApp%20as%20Client%20Application%0A%20%20%20%20participant%20User%0A%20%20%20%20participant%20CE_API%20as%20CE%20API%0A%0A%20%20%20%20User-%3E%3EClientApp%3A%20Clicks%20%22Add%20to%20Cart%22%20for%20Product%20B%20(no%20variants)%0A%20%20%20%20ClientApp-%3E%3EClientApp%3A%20Get%20stored%20Cart%20ID%20'cart123'%0A%20%20%20%20ClientApp-%3E%3ECE_API%3A%20POST%20%2Fcarts%2Fcart123%2Fitems%0A%20%20%20%20activate%20CE_API%0A%20%20%20%20CE_API--%3E%3EClientApp%3A%20200%20OK%20(Response%3A%20Updated%20Cart%20Object)%0A%20%20%20%20deactivate%20CE_API%0A%20%20%20%20ClientApp-%3E%3EClientApp%3A%20Update%20cart%20UI%0A%0A%20%20%20%20User-%3E%3EClientApp%3A%20Changes%20quantity%20of%20Item%20A%20(Variant%20X)%20to%202%20in%20cart%20view%0A%20%20%20%20ClientApp-%3E%3ECE_API%3A%20POST%20%2Fcarts%2Fcart123%2Fitems%20(Body%3A%20%7Bproduct_id%3A%20A%2C%20variant_id%3A%20X%2C%20quantity%3A%202%7D)%0A%20%20%20%20activate%20CE_API%0A%20%20%20%20CE_API--%3E%3EClientApp%3A%20200%20OK%20(Response%3A%20Updated%20Cart%20Object)%0A%20%20%20%20deactivate%20CE_API%0A%20%20%20%20ClientApp-%3E%3EClientApp%3A%20Update%20cart%20UI%0A%0A%20%20%20%20User-%3E%3EClientApp%3A%20Clicks%20%22Remove%22%20for%20Item%20B%0A%20%20%20%20ClientApp-%3E%3ECE_API%3A%20POST%20%2Fcarts%2Fcart123%2Fitems%20(Body%3A%20%7Bproduct_id%3A%20B%2C%20variant_id%3A%20null%2C%20quantity%3A%200%7D)%0A%20%20%20%20activate%20CE_API%0A%20%20%20%20CE_API--%3E%3EClientApp%3A%20200%20OK%20(Response%3A%20Updated%20Cart%20Object%20without%20Item%20B)%0A%20%20%20%20deactivate%20CE_API%0A%20%20%20%20ClientApp-%3E%3EClientApp%3A%20Update%20cart%20UI" />
    </Frame>
  </Accordion>

  <Accordion title="Retrieving Cart on Page Load / After Login">
    <Frame>
      <iframe title="Retrieving Cart on Page Load / After Login" allowfullscreen width="100%" height="500" src="https://mermaid.tarkai.dev/embed?definition=sequenceDiagram%0A%20%20%20%20participant%20ClientApp%20as%20Client%20Application%0A%20%20%20%20participant%20User%0A%20%20%20%20participant%20CE_API%20as%20CE%20API%0A%0A%20%20%20%20alt%20Client%20has%20Cart%20ID%20('cart123')%0A%20%20%20%20%20%20%20%20ClientApp-%3E%3ECE_API%3A%20GET%20%2Fcarts%2Fcart123%20(Header%3A%20Auth%20Bearer)%0A%20%20%20%20%20%20%20%20activate%20CE_API%0A%20%20%20%20%20%20%20%20CE_API--%3E%3EClientApp%3A%20200%20OK%20(Cart%20Object)%0A%20%20%20%20%20%20%20%20deactivate%20CE_API%0A%20%20%20%20else%20Client%20lost%20Cart%20ID%2C%20but%20has%20User%20ID%20('userXYZ')%0A%20%20%20%20%20%20%20%20ClientApp-%3E%3ECE_API%3A%20GET%20%2Fcarts%2Fusers%2FuserXYZ%20(Header%3A%20Auth%20Bearer)%0A%20%20%20%20%20%20%20%20activate%20CE_API%0A%20%20%20%20%20%20%20%20CE_API--%3E%3EClientApp%3A%20200%20OK%20(Cart%20Object)%0A%20%20%20%20%20%20%20%20deactivate%20CE_API%0A%20%20%20%20else%20No%20active%20cart%20for%20user%0A%20%20%20%20%20%20%20%20ClientApp-%3E%3ECE_API%3A%20GET%20%2Fcarts%2Fusers%2FuserXYZ%20(Header%3A%20Auth%20Bearer)%0A%20%20%20%20%20%20%20%20activate%20CE_API%0A%20%20%20%20%20%20%20%20CE_API--%3E%3EClientApp%3A%20404%20Not%20Found%0A%20%20%20%20%20%20%20%20deactivate%20CE_API%0A%20%20%20%20end%0A%20%20%20%20ClientApp-%3E%3EClientApp%3A%20Update%20UI%20based%20on%20received%20cart%20data%20or%20show%20empty%20cart" />
    </Frame>
  </Accordion>
</AccordionGroup>
