# Cart API

> lifecycle.cart, lifecycle.onCart and lifecycle.setVisible — reading the live cart snapshot and showing or hiding content from section scripts and custom cart modules.

Canonical URL: https://77865786950d:3005/scripting/cart

This page is the API reference. For building a module end to end (drafting,
regions, conditions, styling and publishing), see
[Custom cart modules](/cart/custom-modules).

## Cart module arguments

A custom cart module's script receives
`root, section, lifecycle, motion, MutationObserver, setTimeout, setInterval, requestAnimationFrame`.

- **`root`** and **`lifecycle.root`** are the `[data-cart-custom-module]`
  wrapper around your authored `<section>`.
- **`section`** is a deprecated alias of `root`.
- Dispatch cart commands from `root` (or `section`) with `bubbles: true`, and
  listen on the wrapper for responses.

Page sections can read the cart with the same members; they dispatch commands
from `section`.

## lifecycle.cart

```ts
readonly lifecycle.cart: CartSnapshot
```

The current cart as a deeply frozen snapshot. Reading it before currency and
prices are known throws
`Cart currency or prices are not available yet; subscribe with lifecycle.onCart.`
Prefer `onCart` unless you know the cart has loaded.

```ts
type Money = { amount: string; currencyCode: string; minor: number };

interface CartSnapshot {
  status: "idle" | "pending" | "error";
  itemCount: number;
  currency: string;
  subtotal: Money; total: Money; compareAtSubtotal: Money; savings: Money;
  discountCodes: Array<{ code: string; applicable: boolean;
    evaluation?: "not_evaluated" | "computed" | "confirmed" }>;
  lines: Array<{
    id: string; variantId: string; productId: string; handle: string;
    title: string; variantTitle: string; quantity: number;
    price: Money; compareAtPrice: Money | null; lineTotal: Money;
    sellingPlanId: string | null; attributes: Record<string, string>;
    tags: string[]; collectionIds: string[]; isRewardGift: boolean;
  }>;
  rewards: {
    next: { id: string; type: string; title: string; threshold: Money; remaining: Money } | null;
    unlocked: Array<{ id: string; type: string; title: string }>;
    applied?: Array<{ id: string; type: string; title: string }>;
    chosenGiftVariantId: string | null;
  };
  context: {
    market: string; locale: string; pageHandle: string; pageType: string;
    utm: Record<string, string>;
    customer: { loggedIn: boolean; returning: boolean };
  };
}
```

Use `minor` (integer minor units) for comparisons and `amount` for display.
`lexsis_cart.capabilities` returns the same shape as `snapshot_schema`.

## lifecycle.onCart

```ts
lifecycle.onCart(
  callback: (snapshot: CartSnapshot, previous: CartSnapshot | null) => void,
): () => void
```

Calls back with the first settled snapshot (`previous` is `null`), then after
each change, at most once per animation frame. Pending states are skipped, so
the callback only sees settled carts. Returns an unsubscribe function; it is
also removed when the section stops. The callback runs on the
[callback budget](/scripting/timers-and-observers#watchdog).

```js
lifecycle.onCart((cart) => {
  const next = cart.rewards.next;
  lifecycle.setVisible(Boolean(next && next.remaining.minor > 0));
  if (next) label.textContent = `${next.remaining.amount} to go for ${next.title}`;
});
```

## lifecycle.setVisible

```ts
lifecycle.setVisible(visible: boolean): void
```

Sets `hidden` on `root`. In a cart module it also sets `hidden` on the authored
top-level `<section>`, so one call controls both wrappers.

A cart module whose top-level `<section>` is authored with `hidden` gets the
compile warning `hidden_root_section`; reveal it with
`lifecycle.setVisible(true)`.

## Cart commands

Scripts change the cart by dispatching documented events, never by calling
Shopify or `/cart/*.js` (rejected as `direct_cart_mutation`):

| Event | Detail (plus `requestId`, 1–128 characters) |
|---|---|
| `lx:cart:add-items` | items to add |
| `lx:cart:update-line` | `lineId`, `quantity` (0–99) |
| `lx:cart:remove-line` | `lineId` |
| `lx:cart:apply-code` / `lx:cart:remove-code` | `code` |
| `lx:cart:set-attributes` | `attributes` (merged; `_lx_` keys rejected) |
| `lx:cart:set-note` | `note` (up to 5,000 characters) |
| `lx:cart:choose-gift` | `rewardId`, `variantId` |
| `lx:cart:swap-variant` | `lineId`, `variantId`, optional `quantity` |
| `cart:open` | Opens the cart drawer |

`lexsis_cart.capabilities` returns the full `commands` contract with response
events and errors. The validation codes are listed under
[Validation and errors](/scripting/validation#cart-command-checks).
