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

> ## Agent Instructions
> For new direct REST integrations, use the v2026-04 surfaces. The @fluid-app FairShare SDK continues to use its own published public-v2025-06 contract.
> Authenticate with the header Authorization: Bearer <token>; public storefront read endpoints require no auth.
> Lists use cursor pagination via the page[cursor] and page[limit] query params; follow meta.pagination.next_cursor until it is null.
> Never use /api/company/v1 or /api/v1 paths, page/per_page params, or offset pagination — they are legacy.
> The OpenAPI specs under api-reference/ are the authoritative contracts; prefer them over prose when in doubt. api-reference/storefront-v2026-04.yaml covers the v2026-04 storefront surface (/api/v202604/... paths); api-reference/auth-v0.yaml covers the unversioned auth surface (/api/... paths — authentication, MFA, social auth, and token exchange); api-reference/checkout-v2026-04.yaml covers the v2026-04 checkout surface (/api/checkout/v2026-04/... paths — carts, cart auth, discounts, items, subscriptions, orders, enrollments, and store config); api-reference/public-v2025-06.yaml covers the Public SDK surface used by the @fluid-app FairShare SDK, including its parallel cart lifecycle, browser integrations, versioned payment callbacks, unversioned public utilities, and the cart price-override operation; api-reference/payment-v2026-04.yaml covers the v2026-04 payment gateway admin surface (/api/payment/v2026-04/... paths, bearer-authenticated — gateway CRUD, gateway purchase/authorize/$0-verify, transaction list/show and capture/void/credit, and merchant payment configuration); api-reference/payments-v2026-04.yaml covers the v2026-04 cart payment surface (/api/payments/v2026-04/carts/{cart_token}/... paths, authenticated by the cart token in the path with no bearer — payment-method selection, VGS card tokenization, 3D Secure verification, and PayPal/Braintree/Klarna/Apple Pay flows); api-reference/commerce-v2026-04.yaml covers the v2026-04 commerce order-editing surface (/api/v202604/orders/{order_id}/edits paths, bearer-authenticated — post-checkout order edits that atomically insert items and add adjustments/discounts, with an optional dry-run preview); api-reference/webhooks-v0.yaml covers the unversioned webhooks surface (/api/... paths — webhook registration, delivery payloads, callback registrations, company events, and webhook/callback schemas).
> Successful responses wrap the resource payload alongside a top-level integer status and a meta object.

# Build a Shopping Cart with Fluid: Cart API and SDK Guide

> Learn how to build a shopping cart using Fluid's cart API and FairShare SDK — including products, cart creation, real-time updates, and checkout.

Fluid gives you everything you need to build a fully functional shopping cart — a product catalog API, a cart API for managing line items, the FairShare SDK for client-side interactions, and webhooks for real-time event handling. Follow the steps below to go from fetching your first product to completing a checkout.

<Info>
  This guide shows two cart APIs side by side: the direct REST calls below go to
  the Checkout API, while the `@fluid-app` FairShare SDK calls the Fluid Public
  SDK API. Both read and write the same cart records, but their request shapes
  differ. Drive any one cart through a single surface. See [Choosing a cart
  surface](/api/choosing-a-cart-surface).
</Info>

<Tip>
  Use the built-in `<fluid-cart-widget>` custom element for a zero-code cart UI. Drop it anywhere in your HTML and it renders a fully styled cart drawer with no additional configuration required.
</Tip>

<Steps>
  <Step title="Fetch Product Details">
    Before adding anything to a cart, retrieve the product you want to sell. The public product read is unauthenticated — no token required — and resolves a product by its URL **slug** on your company subdomain:

    ```javascript theme={null}
    const response = await fetch(
      'https://{company}.fluid.app/api/v202604/products/scrute-farms-beet-blend'
    );

    const { product } = await response.json();
    console.log(product.title, product.variants);
    ```

    The product is returned under a `product` envelope. It carries the display `title`, `pricing`, stock status, media, and a `variants` array — each variant has the `id` you pass when adding items to the cart. See the [Public product by slug endpoint](/api-reference/storefront/public-product-by-slug) reference for the full response schema.
  </Step>

  <Step title="Create a Cart">
    Create a new cart for the current session with `POST /api/checkout/v2026-04/carts`. The body requires `fluid_shop` (your company subdomain) and `country_code` (an ISO country code); you can seed the cart with an `items` array in the same call. Creating a cart is a public operation — it needs no Bearer token.

    ```bash theme={null}
    curl -X POST https://api.fluid.app/api/checkout/v2026-04/carts \
      -H "Content-Type: application/json" \
      -d '{
        "fluid_shop": "acme",
        "country_code": "US"
      }'
    ```

    The created cart is returned under a `cart` key, including the `cart_token` — store this in the user's session or local storage, since it identifies the cart for every subsequent operation. The hosted checkout link comes back as `meta.checkout_url`. See the [Create a cart endpoint](/api-reference/carts/create-a-cart) reference for the full response schema.
  </Step>

  <Step title="Add Items to the Cart">
    You have two approaches for adding items to a cart.

    **Option A — FairShare SDK (recommended for client-side apps)**

    Call `addCartItems()` with an array of items — each with a `variant_id` and `quantity`:

    ```javascript theme={null}
    await window.FairShareSDK.addCartItems([
      {
        variant_id: 123,
        quantity: 2
      }
    ]);
    ```

    This method posts to the Fluid Public SDK API's [Adds items to cart](/api-reference/carts/adds-items-to-cart) operation — a different operation from the one Option C calls. See [Cart API](/sdk/cart-api) for the operation behind every SDK cart method.

    **Option B — Declarative HTML attribute**

    Add a `data-fluid-add-to-cart` attribute to any button, setting its value to the variant ID. The SDK intercepts clicks and handles the API call automatically:

    ```html theme={null}
    <button data-fluid-add-to-cart="123456">
      Add to Cart
    </button>
    ```

    **Option C — Direct API call**

    Use `POST /api/checkout/v2026-04/carts/{cart_token}/items` to add line items
    directly. This example adds one new variant. See the endpoint reference for
    the current authentication model and the full set of supported batch shapes.

    ```bash theme={null}
    curl -X POST https://api.fluid.app/api/checkout/v2026-04/carts/ct_7Hq2Kd9Rm4bV1nX/items \
      -H "Content-Type: application/json" \
      -d '{
        "items": [
          {
            "variant_id": 123,
            "quantity": 2
          }
        ]
      }'
    ```

    See the [Add items to cart endpoint](/api-reference/cart-items/add-items-to-cart) reference for the full request and response schema.
  </Step>

  <Step title="Display the Cart Count">
    Render a live item count anywhere on the page using the `fluid-cart-count` element. The SDK keeps it in sync automatically as items are added or removed:

    ```html theme={null}
    <span id="fluid-cart-count">0</span>
    ```

    You can style this element freely with CSS. The SDK sets its `textContent` to the current total item count whenever the cart changes.
  </Step>

  <Step title="Handle Checkout">
    When the customer is ready to purchase, send them to checkout using the SDK or the URL returned in the cart response.

    **Via the FairShare SDK:**

    ```javascript theme={null}
    // Redirect to the hosted checkout page
    window.FairShareSDK.checkout();

    // Or retrieve the URL to build your own checkout button
    const url = await window.FairShareSDK.getCheckoutUrl();
    window.location.href = url;
    ```

    **Via the cart response:**

    The `meta.checkout_url` returned when you created the cart is always valid. Redirect the user directly to that URL at any point.
  </Step>
</Steps>

## Real-Time Cart Updates

Subscribe to cart events using Fluid webhooks to trigger downstream actions — send abandonment emails, update inventory, or sync to your CRM in real time.

### Register a Webhook

Create a subscription with `POST /api/company/webhooks`. A subscription pairs a `resource` with an `event` on that resource (the short event name, e.g. `updated`), the `url` Fluid delivers to, and an `auth_token` shared secret you use to verify deliveries:

```bash theme={null}
curl -X POST https://api.fluid.app/api/company/webhooks \
  -H "Authorization: Bearer <your_company_token>" \
  -H "Content-Type: application/json" \
  -d '{
    "webhook": {
      "resource": "cart",
      "event": "updated",
      "url": "https://yourapp.com/webhooks/cart",
      "active": true,
      "http_method": "post",
      "auth_token": "<a-long-random-secret>"
    }
  }'
```

Discover the valid `resource`/`event` pairs before you register with `GET /api/company/webhooks/resources`. For registering, managing, verifying, and inspecting webhooks in full, see the [Register and handle webhooks](/api/guides/webhooks) guide.

### Handle Incoming Events

Every delivery arrives as the envelope `{ id, identifier, name, timestamp, payload }`, with the resource data keyed by its own name inside `payload` — a cart delivery carries `payload.cart`. Always verify the signature against your `auth_token` before trusting a delivery (see the [webhooks guide](/api/guides/webhooks) for the exact HMAC scheme):

```javascript theme={null}
const express = require('express');
const app = express();
app.use(express.json());

app.post('/webhooks/cart', (req, res) => {
  // Verify the X-Fluid-Signature header first — see the webhooks guide.
  const { name, payload } = req.body;
  const cart = payload.cart;

  console.log(`Received ${name} for cart ${cart.cart_token}`);
  // Enqueue the work and acknowledge quickly.

  res.sendStatus(200);
});

app.listen(3000);
```
