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

# Cart API

> Managing shopping carts and checkout flows for storefront applications

# Kibo Cart API Developer Guide

<CardGroup cols={2}>
  <Card title="Cart And Checkout" icon="book-open" href="/concept-guides/cart-and-checkout" horizontal data-rec="developer-backlink">
    Understand cart and checkout workflows
  </Card>

  <Card title="Cart Takeover" icon="book-open" href="/pages/cart-takeover" horizontal data-rec="developer-backlink">
    Configure cart takeover functionality
  </Card>

  <Card title="Share Cart Across Sites" icon="book-open" href="/pages/share-cart-across-sites" horizontal data-rec="developer-backlink">
    Enable cross-site cart sharing
  </Card>

  <Card title="Quick Orders" icon="book-open" href="/pages/quick-orders" horizontal data-rec="developer-backlink">
    Set up quick orders for B2B customers
  </Card>
</CardGroup>

## Understanding Cart in Kibo

In Kibo, a **Cart** is more than just a list of products; it's a transactional object that represents a shopper's entire potential purchase. It holds the items, quantities, applied coupons, and calculated totals. Kibo's philosophy is to treat the cart as a "draft" of an order that can exist for both guest and logged-in shoppers. When a guest with a cart logs in, Kibo intelligently merges their anonymous cart with any previous cart they had, creating a seamless shopping experience. The Cart API is part of the **Storefront API group**, meaning it's designed to be called securely from a front-end application.

***

## How This Domain Fits Into Kibo

The **Cart** is the central hub of the shopping experience, connecting several key domains:

* **Catalog**: The cart holds references to products (`productCode`) from the catalog. It pulls in pricing and other details.
* **Promotions**: The Cart API is where you apply coupon codes, and Kibo's promotion engine calculates the discounts directly on the cart object.
* **Customer**: Carts can be associated with a customer account, allowing them to be persisted between sessions.
* **Checkout**: The cart is the direct input for creating a `Checkout` object. The checkout process is essentially the act of gathering the remaining information (shipping, billing, payment) needed to convert the cart into an order.
* **Orders**: Once the checkout is complete, the cart's data is used to create a permanent `Order` record in Kibo.

***

## Prerequisites

* Kibo Application Key
* Node.js 16+ with TypeScript
* Familiarity with REST APIs and front-end development concepts

***

## What You'll Learn

After completing this guide, you'll understand:

* How Kibo structures cart data for storefront interactions (based on official API specs)
* The key patterns for creating, managing, and converting a shopper's cart
* Common workflows like adding items, applying coupons, and updating quantities
* How to avoid the most common beginner mistakes when working with carts
* How to transition a cart into the checkout and order phases of the e-commerce lifecycle

***

## Kibo Cart Fundamentals

### How Kibo Organizes Cart Data

The core object is the `Cart`, which contains an array of `CartItem` objects.

* **`Cart`**: The parent object. It has a unique `id`, a `total`, a list of applied `coupons`, and other summary information. For guest shoppers, this cart is tracked via a cookie or session. For logged-in shoppers, it's associated with their `customerAccountId`.
* **`CartItem`**: Represents a single line item in the cart. It contains a `product` object (with details like `productCode` and `name`), the `quantity`, and a `total` for that line.

### Key Kibo Patterns You'll See Everywhere

**Authentication Pattern:**
Storefront APIs, including the Cart API, are secured using OAuth 2.0 Bearer tokens. This applies to both application-level and shopper-level authentication.

1. **Application Authentication:**
   * **When:** Used for server-to-server requests or calls that are not on behalf of a specific, logged-in shopper (e.g., using explicit `cartId` APIs).
   * **How:** Your application authenticates using its credentials (e.g., Client ID and Shared Secret) via an OAuth flow to obtain an **application-level Bearer token**.
   * **Usage:** This token is passed in the request header: `Authorization: Bearer <application_token>`.

2. **Shopper Authentication:**
   * **When:** Used for requests made in the context of a logged-in shopper, such as managing the `/current` cart.
   * **How:** The shopper logs in via the Customer Auth Ticket API (`POST /api/commerce/customer/authtickets`), which returns a `jwtAccessToken`.
   * **Usage:** This shopper-specific JWT is passed in the request header: `Authorization: Bearer <shopper_jwtAccessToken>`. The Kibo SDK, when configured with this token, handles this automatically.

**Request/Response Structure:**
Most Cart API calls (`addItemToCartByCartId`, `updateCartItemQuantityByCartId`, `applyCouponByCartId`) are transactional. After you perform an action, the API returns the **entire updated Cart object**. This is a key pattern: you don't need to re-fetch the cart after every change; the API response gives you the latest state, which you can use to update your UI.

**Error Handling Approach:**
If an operation fails (e.g., adding an out-of-stock item, applying an invalid coupon), the SDK will throw an error containing Kibo's standard error object, including an `errorCode` and `message`.

**API Documentation Reference:**
Throughout this guide, we'll reference specific endpoints. Find complete specs at:
[`/api-reference/cart/get-cart-summary`](/api-reference/cart/get-cart-summary)

***

### Common Cart Workflows

1. **Starting a Session**: Creating a cart to get a `cartId`.
2. **Building the Cart**: Adding products, updating quantities, and applying discounts using the `cartId`.
3. **Finalizing the Purchase**: Converting the cart into a checkout or a direct order.

Let's explore each pattern step by step.

***

## Add an Item to the Cart (Application Token / Explicit `cartId`)

This is the recommended approach for server-side integrations or when using a Kibo **Application Token**, where you need to explicitly manage the cart's lifecycle.

### When You Need This

You need this when a server-side process or application needs to create and manage a cart. This gives you direct control over which cart is being modified.

***

### API Documentation Reference

* **Endpoint:** `POST /api/commerce/carts/{cartId}/items`
* **Method:** `POST`
* **API Docs:** [`/api-reference/cart/add-item-to-cart-by-cartid`](/api-reference/cart/add-item-to-cart-by-cartid)

***

### Understanding the Kibo Approach

Using an explicit cart ID requires a two-step process. First, you must **create a cart** to get a unique `cartId` (see the "Create a New Cart" example below). Then, you use that `cartId` for all subsequent operations, like adding an item.

***

### Code Structure Walkthrough

```typescript theme={null}
// We'll build this step by step:
// 1. **Configuration**: Create a central Configuration instance with our storefront API credentials.
// 2. **API Client Instantiation**: Create a dedicated client for the Storefront Cart API.
// 3. **Data Preparation**: Construct the `CartItem` object with the product code and quantity.
// 4. **API Call**: Use the client to call the `addItemToCartByCartId` method, passing the `cartId` you created.
```

***

#### Step-by-Step Implementation

**Step 1: Setting Up the Foundation**

```ts theme={null}
// Essential imports for Cart operations.
// We import the Configuration class and the specific API clients we need.
import { Configuration } from "@kibocommerce/rest-sdk";
import { CartApi, CartItem, Cart } from "@kibocommerce/rest-sdk/clients/Commerce";

// Configuration setup for storefront. This uses your public Application Key.
const configuration = new Configuration({
    tenantId: process.env.KIBO_TENANT_ID,
    siteId: process.env.KIBO_SITE_ID,
    // This is your public Application Key from Dev Center
    appKey: process.env.KIBO_APP_KEY,
    authHost: process.env.KIBO_AUTH_HOST,
});
```

**Step 2: Understanding the Data Flow**
We'll create a `CartItem` object. This object tells the API which product to add (via its `productCode`) and how many. For products with options (like color or size), we would also include an `options` array. The API will validate this information against the catalog, check inventory, and if successful, add it to the specified cart, returning the entire updated cart object.

**Step 3: The Core Implementation**

```ts theme={null}
// Complete working example that ACTUALLY WORKS with the Kibo API.
// Assumes you have already called createCart() and have a cartId.
async function addProductToCart(cartId: string, productCode: string, quantity: number): Promise<Cart> {
    // 1. Instantiate a dedicated client for the Storefront Cart resource.
    const cartClient = new CartApi(configuration);

    // 2. Prepare the request body. This object must match the CartItem schema.
    const cartItem: CartItem = {
        quantity: quantity,
        product: {
            productCode: productCode,
            // For configurable products, you would add an options array here, e.g.,
            // options: [
            //    { attributeFQN: 'tenant~color', value: 'blue' },
            //    { attributeFQN: 'tenant~size', value: 'medium' }
            // ]
        },
    };

    try {
        // 3. Call the method on the client.
        console.log(`Adding ${quantity} of product ${productCode} to cart ${cartId}...`);
        const addedCartItem = await cartClient.addItemToCartByCartId({
            cartId: cartId,
            cartItem: cartItem
        });

        console.log("Success! ", produtCode, " added to cart.");
        return updatedCart;
    } catch (error) {
        console.error("API Error adding item to cart:", JSON.stringify(error, null, 2));
        throw error;
    }
}
```

***

### What Just Happened? (Code Explanation)

* The **setup phase** created a `Configuration` object using the public `appKey`, which is the correct and secure way to authenticate storefront requests.
* The **API call** was made using an instance of `CartApi` and the `addItemToCartByCartId` method. This requires us to have a `cartId` *before* we can call it. This `cartId` is typically retrieved from a `createCart` call (see 'Create a New Cart' example).
* The **response handling** leverages Kibo's pattern of returning the full, updated `Cart` object upon success, providing immediate access to the new total and item count without a follow-up request.
* Kibo will populate the rest of the product information from the data in the Catalog.

***

### Common Beginner Mistakes

**Mistake 1:** Forgetting to include product options for configurable products.

```ts theme={null}
// Wrong - This will fail with a validation error for a T-shirt that requires a color and size.
const item = { product: { productCode: 'TSHIRT-01' }, quantity: 1 };

// Correct - Provide the selected option values in the `options` array.
const item = {
    product: {
        productCode: 'TSHIRT-01',
        options: [
            { attributeFQN: 'tenant~color', value: 'blue' },
            { attributeFQN: 'tenant~size', value: 'medium' }
        ]
    },
    quantity: 1
};
```

***

## Add an Item to the Cart (Shopper Token / `/current` APIs)

Kibo also provides session-based `/current` APIs. These are designed to be used with an **authenticated shopper's JSON Web Token (JWT)**.

When a shopper logs in, your application should exchange their credentials for a customer auth ticket.

* **Auth Ticket API:** `POST /api/commerce/customer/authtickets`
* **API Docs:** [`/api-reference/storefrontauthticket/create-user-auth-ticket`](/api-reference/storefrontauthticket/create-user-auth-ticket)

This endpoint returns an `jwtAccessToken`. When you make subsequent API calls (like to the Cart API) and provide this token in the `Authorization` header, the Kibo platform gains the context of that specific shopper.

In this authenticated context, the `/current` keyword in API paths becomes a powerful shortcut. It automatically resolves to the cart associated with the logged-in shopper, eliminating the need to manually track a `cartId` on the client side.

### Example: Add an Item to the Authenticated Shopper's Cart

This workflow assumes you have already obtained and configured the Kibo SDK to use the shopper's `accessToken`.

Here is the updated section, modified to use a client-side `fetch` example and simulate token retrieval.

***

### API Documentation Reference

* **Endpoint:** `POST /api/commerce/carts/current/items`
* **Method:** `POST`
* **API Docs:** [`/api-reference/cart/add-item-to-cart`](/api-reference/cart/add-item-to-cart)

### Understanding the Kibo Approach

With an authenticated shopper token, Kibo's `/current/items` endpoint is seamless. If a cart doesn't exist for that shopper, Kibo automatically creates one and associates it with their account. If they already have a cart (perhaps from a previous session), Kibo adds the item to that existing cart.

You don't need to manage the `cartId` manually; the shopper's `Authorization: Bearer <token>` header provides all the necessary context for the Kibo platform to find and update the correct cart.

### Code Implementation (Client-Side Fetch)

```ts theme={null}
/**
 * Simulates retrieving the shopper's JWT.
 * In a real application, this would come from localStorage, sessionStorage,
 * or a secure cookie after the shopper logs in.
 */
async function fetchAnonShopperAuthToken(username: string, password: string): Promise<string | null> {
  console.log(`Attempting to log in as ${username}...`);

  const KIBO_API_HOST = process.env.REACT_APP_KIBO_API_HOST; // e.g., "t12345.sandbox.mozu.com"
  const appToken = getApplicationToken(); // Get the app-level auth token

  // The endpoint to exchange credentials for a shopper token
  const apiUrl = `https://://${KIBO_HOST}/api/customer/authtickets/anonymousshopper`;

  const fetchOptions = {
    method: 'GET',
    headers: {
      'Content-Type': 'application/json',
    }
  };

  try {
    const response = await fetch(apiUrl, fetchOptions);

    if (!response.ok) {
      // Handle login failures (e.g., 401 Invalid Credentials)
      const errorData = await response.json();
      console.error('Login Error:', errorData.message || 'Invalid username or password');
      return null;
    }

    const authTicket = await response.json();

    const shopperToken = authTicket.jwtAccessToken;
    
    if (shopperToken) {
      console.log("Shopper login successful. JWT retrieved.");
      // In a real app, you would now store this token securely
      // (e.g., localStorage.setItem('shopperToken', shopperToken));
      return shopperToken;
    } else {
      console.error("Login successful, but no jwtAccessToken was returned.");
      return null;
    }

  } catch (error) {
    console.error("Fetch Error during login:", error);
    return null;
  }
}

/**
 * Adds an item to the /current cart using the native Fetch API.
 * This assumes the shopper is logged in and their token is available.
 */
async function addItemToShopperCart(productCode: string, quantity: number): Promise<any> {
  const shopperToken = fetchAnonShopperAuthToken();
  
  if (!shopperToken) {
    throw new Error("Cannot add to cart. Shopper is not authenticated.");
  }

  
  const apiUrl = `/api/commerce/carts/current/items`;

  const cartItemBody = {
    quantity: quantity,
    product: {
      productCode: productCode,
      // For configurable products, you would add an options array here
      // options: [
      //   { attributeFQN: 'tenant~color', value: 'blue' }
      // ]
    },
  };

  const fetchOptions = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      // The shopper's JWT is passed as the Bearer token
      'Authorization': `Bearer ${shopperToken}`,
    },
    body: JSON.stringify(cartItemBody),
  };

  try {
    console.log(`Adding ${quantity} of ${productCode} to the /current shopper cart...`);
    const response = await fetch(apiUrl, fetchOptions);

    if (!response.ok) {
      const errorData = await response.json();
      console.error('API Error:', errorData.message || 'Unknown error');
      throw new Error(`API request failed: ${response.status} ${response.statusText}`);
    }

    const updatedCart = await response.json();
    
    console.log("Success! Shopper's cart now has", updatedCart.items?.length, "items.");
    return updatedCart;

  } catch (error) {
    console.error("Fetch Error adding item to shopper's cart:", error);
    throw error;
  }
}
```

### Key Takeaway

* Use **explicit `cartId` APIs** (e.g., `createCart`, `addItemToCartByCartId`) when authenticating with an **Application Bearer Token** (server-to-server, app-level context).
* Use **`/current` APIs** (e.g., `/api/commerce/carts/current/items`) when authenticating with a **Shopper JWT** (client-side, logged-in shopper context).

***

## Advanced Patterns & Multiple Examples

The following examples use the **explicit `cartId`** pattern, which is common for server-side management.

### Pattern 1: Converting a Cart to a Checkout

**Business Scenario:**
After a shopper has added items to their cart, they click the "Checkout" button. You need to transition them to the checkout process where they can enter shipping and payment information.

**Kibo's Architecture Consideration:**
This is a handoff between two different domains. The `Cart` is the input used to create a new `Order` object. The `OrderApi` takes a `cartId` and creates a new, persistent checkout with its own unique ID. This new order object will contain all the items from the cart, plus new sections for shipping info, billing info, and payments.

```ts theme={null}
import { Configuration } from "@kibocommerce/rest-sdk";
import { OrderApi, Order } from "@kibocommerce/rest-sdk/clients/Commerce";

async function convertCartToOrder(config: Configuration, cartId: string): Promise<Order> {
    const orderClient = new OrderApi(config);
    try {
        if (!cartId) {
            throw new Error("A valid cartId must be provided.");
        }
        console.log(`Submitting order from cart ${cartId}...`);

        // This uses the OrderApi, showing cross-domain integration.
        const newOrder = await orderClient.createOrder({ cartId: cartId });
        console.log(`Successfully created order ${newOrder.id}.`);
        return newOrder;
    } catch (error) {
        console.error("Failed to convert cart to order:", JSON.stringify(error, null, 2));
        throw error;
    }
}
```

***

### More Real-World Examples

**Example 2: Create a New Cart**
This is the first step for any workflow. You call `createCart` to get a new cart object and its ID.

```ts theme={null}
import { Configuration } from "@kibocommerce/rest-sdk";
import { CartApi, Cart } from "@kibocommerce/rest-sdk/clients/Commerce";

async function createNewCart(config: Configuration): Promise<Cart> {
    const cartClient = new CartApi(config);
    try {
        console.log("Creating a new cart...");
        const cart = await cartClient.createOrCreateCart();
        console.log(`New cart created with ID: ${cart.id}`);
        return cart;
    } catch (error) {
        console.error("Failed to create cart:", JSON.stringify(error, null, 2));
        throw error;
    }
}
```

**Example 2b: Get an Existing Cart by ID**
Once you have a `cartId`, you can retrieve it at any time.

```ts theme={null}
import { Configuration } from "@kibocommerce/rest-sdk";
import { CartApi, Cart } from "@kibocommerce/rest-sdk/clients/Commerce";

async function getExistingCart(config: Configuration, cartId: string): Promise<Cart> {
    const cartClient = new CartApi(config);
    try {
        console.log(`Getting cart with ID: ${cartId}...`);
        const cart = await cartClient.getCart({ cartId: cartId });
        console.log(`Cart ${cart.id} retrieved.`);
        return cart;
    } catch (error) {
        console.error("Failed to get cart:", JSON.stringify(error, null, 2));
        throw error;
    }
}
```

**Example 3: Apply a Promotion (Coupon) to the Cart**

```ts theme={null}
import { Configuration } from "@kibocommerce/rest-sdk";
import { CartApi, Cart } from "@kibocommerce/rest-sdk/clients/Commerce";

async function applyCoupon(config: Configuration, cartId: string, couponCode: string): Promise<Cart> {
    const cartClient = new CartApi(config);
    try {
        console.log(`Applying coupon "${couponCode}" to cart ${cartId}...`);
        // The API call returns the entire updated cart object with the discount applied.
        const updatedCart = await cartClient.applyCoupon({
            cartId: cartId,
            couponCode: couponCode
        });
        console.log("Coupon applied successfully. New total:", updatedCart.total);
        return updatedCart;
    } catch (error) {
        console.error("Failed to apply coupon:", JSON.stringify(error, null, 2));
        throw error;
    }
}
```

**Example 4: Update Cart Item Quantity**

```ts theme={null}
import { Configuration } from "@kibocommerce/rest-sdk";
import { CartApi, Cart } from "@kibocommerce/rest-sdk/clients/Commerce";

async function updateItemQuantity(config: Configuration, cartId: string, cartItemId: string, newQuantity: number): Promise<CartItem | void> {
    const cartClient = new CartApi(config);
    try {
        console.log(`Updating item ${cartItemId} in cart ${cartId} to quantity ${newQuantity}...`);
        if (newQuantity <= 0) {
            // To remove an item, you call `deleteCartItemByCartId`.
            console.log("Quantity is zero or less, removing item...");
            return await cartClient.deleteCartItemByCartId({
                cartId: cartId,
                cartItemId: cartItemId
            });
        } else {
            const updatedCart = await cartClient.updateCartItemQuantityByCartId({
                cartId: cartId,
                cartItemId: cartItemId,
                quantity: newQuantity,
            });
            console.log("Quantity updated. New total:", updatedCart.total);
            return updatedCartItem;
        }
    } catch (error) {
        console.error("Failed to update quantity:", JSON.stringify(error, null, 2));
        throw error;
    }
}
```

**Example 5: Submit an Order Directly from a Cart**
This advanced pattern user the multi-step checkout and is useful for integrations supporting multiple fulfillment destinations in the same purchase.

```typescript theme={null}
// Example 1: Create a Checkout from a Cart ID
import { Configuration } from "@kibocommerce/rest-sdk";
import { CheckoutApi, Checkout } from "@kibocommerce/rest-sdk/clients/Commerce";

async function convertCartToCheckout(config: Configuration, cartId: string): Promise<Checkout> {
    const checkoutClient = new CheckoutApi(config);

    try {
        if (!cartId) {
            throw new Error("A valid cartId must be provided.");
        }
        console.log(`Creating checkout from cart ${cartId}...`);

        // Now, use the cart ID to create a checkout.
        // This is a separate API call to the Checkout resource.
        const newCheckout = await checkoutClient.createCheckoutFromCart({ cartId: cartId });

        console.log(`Successfully created checkout ${newCheckout.id}.`);
        return newCheckout;
    } catch (error) {
        console.error("Failed to convert cart to checkout:", JSON.stringify(error, null, 2));
        throw error;
    }
}
```

***

## Troubleshooting Your Cart Implementation

### Reading Kibo Error Messages

```typescript theme={null}
// Actual error structure from Kibo API
interface KiboApiError {
  errorCode: string;        // e.g., "ITEM_NOT_FOUND"
  message: string;          // "The item requested could not be found."
  correlationId: string;    // For Kibo support
}
```

**Common Error Codes for Cart:**

* `VALIDATION_ERROR`: The most common error. The `CartItem` you tried to add was invalid (e.g., missing options, invalid `productCode`). The error `message` will provide more details.
* `PRODUCT_NOT_IN_CATALOG`: The product is not assigned to the catalog used by the current site.
* `NOT_STOCKED`: You tried to add an item with no inventory, and the site is configured to block backorders.
* `COUPON_INVALID`: The coupon code does not exist, has expired, or is not applicable to the items in the cart.

***

### Common Development Issues

**Issue 1:** 'Cart not found' or 404 error when managing items.

* **Why it happens:** You are trying to use a `cartId` that is invalid, expired, or doesn't exist. This can happen if you don't correctly store the `cartId` after your initial `createCart` call.
* **How to fix it:** Ensure your application state correctly captures and re-uses the `cartId` returned from a `createCart` call.
* **API Reference:** The `createCart` method is the starting point. All other methods like `addItemToCartByCartId` depend on its output.

**Issue 2:** A coupon won't apply, but I know it's valid.

* **Why it happens:** The promotion might have targeting rules. It could be limited to a specific customer segment, a minimum cart value, or specific products. The Storefront API enforces all these rules automatically.
* **How to fix it:** Check the promotion's configuration in Kibo Admin. Make sure the cart's contents and the shopper's context (e.g., logged in or guest) meet all the discount's requirements.
* **API Reference:** [`/api-reference/cart/apply-coupon`](/api-reference/cart/apply-coupon)

***

### Debugging Checklist

When your Cart implementation isn't working:

1. Verify your `Configuration` object uses the public `appKey`.
2. If using shopper-authenticated APIs, verify your `Authorization` JWT is valid and not expired.
3. Check the browser's network tab to see the API response. The error message is often very descriptive.
4. Ensure the `productCode` you're adding is correct, active, and available on the storefront.
5. For configurable products, double-check that the `attributeFQN` and `value` for all required options are correct.
6. Use the `correlationId` from any error message when contacting Kibo support.
