Cart Flow

A complete walkthrough from creating a cart through to a validated, checkout-ready cart.

What you'll build

A full checkout lifecycle that:

  1. Creates a cart with a first item
  2. Adds a second item
  3. Updates the quantity of an item
  4. Removes an item
  5. Sets the delivery specification to delivery
  6. Applies a promo code
  7. Validates the cart

At that point the cart is ready for checkout. How you finish depends on your access level — see Finishing the checkout below.

Prerequisites

  • A Store UUID (staging: e87437f2-3e35-4738-af5e-6307e368255c)
  • A valid JWT token — see the Authentication guide
  • At least two product IDs from the catalog — see the Quick Start
  • cURL or any HTTP client

Setup

All examples use these constants:

STORE_UUID="e87437f2-3e35-4738-af5e-6307e368255c"
BASE_URL="https://ecom-api.staging.blaze.me"
TOKEN="YOUR_JWT_TOKEN"
const STORE_UUID = "e87437f2-3e35-4738-af5e-6307e368255c";
const BASE_URL = "https://ecom-api.staging.blaze.me";
const token = "YOUR_JWT_TOKEN";

const headers = {
  "Content-Type": "application/vnd.api+json",
  Accept: "application/vnd.api+json",
  "X-Store": STORE_UUID,
  Authorization: `Bearer ${token}`,
};

Step 1: Create a Cart with the First Item

Create a cart with one item. The initial request also sets the delivery type and inventory type.

POST /api/v5/carts

cURL

curl -X POST "$BASE_URL/api/v5/carts" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "data": {
      "type": "carts",
      "attributes": {
        "delivery_specification": "pickup",
        "inventory_type": "recreational",
        "item": {
          "product_id": "PRODUCT_A_UUID",
          "quantity": 1
        }
      }
    }
  }'

JavaScript

const createCartRes = await fetch(`${BASE_URL}/api/v5/carts`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    data: {
      type: "carts",
      attributes: {
        delivery_specification: "pickup",
        inventory_type: "recreational",
        item: {
          product_id: "PRODUCT_A_UUID",
          quantity: 1,
        },
      },
    },
  }),
});

const { data: cart } = await createCartRes.json();
const cartId = cart.id;
const itemA = cart.attributes.items[0];
console.log(`Cart created: ${cartId}`);
console.log(`Item: ${itemA.name} x${itemA.quantity} — $${itemA.price}`);

Response

{
  "data": {
    "id": "cart-uuid",
    "type": "carts",
    "attributes": {
      "uuid": "cart-uuid",
      "delivery_specification": "pickup",
      "inventory_type": "recreational",
      "subtotal": 45.00,
      "total": 49.28,
      "tax": 4.28,
      "promo_codes": [],
      "reward_id": null,
      "items": [
        {
          "id": "item-a-uuid",
          "product_id": "PRODUCT_A_UUID",
          "quantity": 1,
          "price": 45.00,
          "name": "Blue Dream"
        }
      ]
    }
  }
}

Save cart-uuid and item-a-uuid — you'll need them in every subsequent step.


Step 2: Add a Second Item

POST /api/v5/carts/{cart_uuid}/items

cURL

curl -X POST "$BASE_URL/api/v5/carts/CART_UUID/items" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "data": {
      "type": "cart_items",
      "attributes": {
        "product_id": "PRODUCT_B_UUID",
        "quantity": 2
      }
    }
  }'

JavaScript

const addItemRes = await fetch(`${BASE_URL}/api/v5/carts/${cartId}/items`, {
  method: "POST",
  headers,
  body: JSON.stringify({
    data: {
      type: "cart_items",
      attributes: {
        product_id: "PRODUCT_B_UUID",
        quantity: 2,
      },
    },
  }),
});

const { data: updatedCart } = await addItemRes.json();
console.log(`Cart now has ${updatedCart.attributes.items.length} items`);
console.log(`New subtotal: $${updatedCart.attributes.subtotal}`);

Response

{
  "data": {
    "id": "cart-uuid",
    "type": "carts",
    "attributes": {
      "subtotal": 105.00,
      "total": 115.03,
      "tax": 10.03,
      "items": [
        {
          "id": "item-a-uuid",
          "product_id": "PRODUCT_A_UUID",
          "quantity": 1,
          "price": 45.00,
          "name": "Blue Dream"
        },
        {
          "id": "item-b-uuid",
          "product_id": "PRODUCT_B_UUID",
          "quantity": 2,
          "price": 30.00,
          "name": "Sour Diesel"
        }
      ]
    }
  }
}

Step 3: Update Item Quantity

Change the quantity of the second item from 2 to 3. The product_id is required even on updates.

PATCH /api/v5/carts/{cart_uuid}/items/{item_uuid}

cURL

curl -X PATCH "$BASE_URL/api/v5/carts/CART_UUID/items/ITEM_B_UUID" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "data": {
      "id": "ITEM_B_UUID",
      "type": "cart_items",
      "attributes": {
        "product_id": "PRODUCT_B_UUID",
        "quantity": 3
      }
    }
  }'

JavaScript

const itemBId = updatedCart.attributes.items[1].id;

const updateRes = await fetch(
  `${BASE_URL}/api/v5/carts/${cartId}/items/${itemBId}`,
  {
    method: "PATCH",
    headers,
    body: JSON.stringify({
      data: {
        id: itemBId,
        type: "cart_items",
        attributes: {
          product_id: "PRODUCT_B_UUID",
          quantity: 3,
        },
      },
    }),
  }
);

const { data: afterUpdate } = await updateRes.json();
const itemB = afterUpdate.attributes.items.find((i) => i.id === itemBId);
console.log(`Item B quantity: ${itemB.quantity}`); // 3
console.log(`New subtotal: $${afterUpdate.attributes.subtotal}`);

Step 4: Remove an Item

Remove the first item (Blue Dream) from the cart.

DELETE /api/v5/carts/{cart_uuid}/items/{item_uuid}

cURL

curl -X DELETE "$BASE_URL/api/v5/carts/CART_UUID/items/ITEM_A_UUID" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN"

JavaScript

const removeRes = await fetch(
  `${BASE_URL}/api/v5/carts/${cartId}/items/${itemA.id}`,
  {
    method: "DELETE",
    headers,
  }
);

const { data: afterRemove } = await removeRes.json();
console.log(`Items remaining: ${afterRemove.attributes.items.length}`); // 1

The response returns the updated cart without the removed item.


Step 5: Set Delivery Specification

Switch from pickup to delivery and provide an address.

PUT /api/v4/carts/{cart_uuid}/delivery-specification

Note: The delivery-specification sub-resource was introduced in v4.

cURL

curl -X PUT "$BASE_URL/api/v4/carts/CART_UUID/delivery-specification" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "data": {
      "id": "CART_UUID",
      "type": "carts",
      "attributes": {
        "delivery_specification": "delivery",
        "address": {
          "address": "456 Oak Avenue",
          "address_line2": "Apt 2B",
          "city": "Los Angeles",
          "state": "CA",
          "zip_code": "90001",
          "country": "US",
          "lat": 34.0522,
          "lng": -118.2437
        }
      }
    }
  }'

JavaScript

const deliveryRes = await fetch(
  `${BASE_URL}/api/v4/carts/${cartId}/delivery-specification`,
  {
    method: "PUT",
    headers,
    body: JSON.stringify({
      data: {
        id: cartId,
        type: "carts",
        attributes: {
          delivery_specification: "delivery",
          address: {
            address: "456 Oak Avenue",
            address_line2: "Apt 2B",
            city: "Los Angeles",
            state: "CA",
            zip_code: "90001",
            country: "US",
            lat: 34.0522,
            lng: -118.2437,
          },
        },
      },
    }),
  }
);

const { data: withDelivery } = await deliveryRes.json();
console.log(
  `Delivery: ${withDelivery.attributes.delivery_specification}`
); // "delivery"

Tip: Before setting a delivery address, verify the store delivers to that location with POST /api/v4/deliveries/stores. See the Store & Delivery guide.


Step 6: Apply a Promo Code

Promo codes are applied via the cart update endpoint. The promo_codes field is an array — you can apply multiple codes.

PUT /api/v5/carts/{cart_uuid}

cURL

curl -X PUT "$BASE_URL/api/v5/carts/CART_UUID" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "data": {
      "id": "CART_UUID",
      "type": "carts",
      "attributes": {
        "promo_codes": ["SAVE10"]
      }
    }
  }'

JavaScript

const promoRes = await fetch(`${BASE_URL}/api/v5/carts/${cartId}`, {
  method: "PUT",
  headers,
  body: JSON.stringify({
    data: {
      id: cartId,
      type: "carts",
      attributes: {
        promo_codes: ["SAVE10"],
      },
    },
  }),
});

const { data: withPromo } = await promoRes.json();
console.log(`Promo codes applied: ${withPromo.attributes.promo_codes}`);
console.log(`Discount reflected in total: $${withPromo.attributes.total}`);

Response

{
  "data": {
    "id": "cart-uuid",
    "type": "carts",
    "attributes": {
      "subtotal": 90.00,
      "total": 89.55,
      "tax": 8.55,
      "promo_codes": ["SAVE10"],
      "items": [
        {
          "id": "item-b-uuid",
          "product_id": "PRODUCT_B_UUID",
          "quantity": 3,
          "price": 30.00,
          "name": "Sour Diesel"
        }
      ]
    }
  }
}

Step 7: Validate the Cart

Before checkout, validate the cart to check stock, pricing, delivery eligibility, and promo code validity.

POST /api/v5/carts/{cart_uuid}/valid

cURL

curl -X POST "$BASE_URL/api/v5/carts/CART_UUID/valid" \
  -H "Content-Type: application/vnd.api+json" \
  -H "Accept: application/vnd.api+json" \
  -H "X-Store: $STORE_UUID" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{
    "data": {
      "type": "carts",
      "attributes": {
        "promo_codes": ["SAVE10"],
        "reward_id": null
      }
    }
  }'

JavaScript

const validateRes = await fetch(
  `${BASE_URL}/api/v5/carts/${cartId}/valid`,
  {
    method: "POST",
    headers,
    body: JSON.stringify({
      data: {
        type: "carts",
        attributes: {
          promo_codes: ["SAVE10"],
          reward_id: null,
        },
      },
    }),
  }
);

if (validateRes.ok) {
  console.log("Cart is valid — ready for checkout");
} else {
  const { errors } = await validateRes.json();
  console.error("Validation failed:", errors);
  // Handle: out of stock, price changes, delivery zone, order minimums, etc.
}

If validation fails, the response includes an errors array with specific reasons (stock, price changes, delivery zone, order minimums, promo validity, schedule availability).



Finishing the checkout

A validated cart can be completed two ways.

Checkout handoff — available to everyone

Redirect the shopper to Blaze-hosted checkout carrying this cart. Blaze handles payment, identity and age verification, and order creation. No certification required.

// Mint a 5-minute handoff token and redirect
const res = await fetch(`${BASE_URL}/api/v1/users/me/access_token`, {
  method: "POST",
  headers: {...headers, Authorization: `Bearer ${TOKEN}`},
  body: JSON.stringify({data: {type: "user_access_tokens", attributes: {}}}),
});
const {data: token} = await res.json();

const site = await (await fetch(`${BASE_URL}/api/v1/store/site`, {headers})).json();
const base = site.data.attributes.url.replace(/\/$/, "");

window.location.assign(
  `${base}/checkout/${CART_UUID}/?access_token=${token.attributes.access_token}&delivery_type=delivery`
);

See the Checkout Handoff guide for the full contract.

API checkout — certified partners only

Create the order yourself via POST /api/v4/orders and process payment through the API. This is restricted to certified partners — see the Certified Checkout Flow example.


Complete Flow Summary

POST   /api/v5/carts                                     → Create cart + first item
POST   /api/v5/carts/{cart_uuid}/items                   → Add second item
PATCH  /api/v5/carts/{cart_uuid}/items/{item_uuid}       → Update quantity
DELETE /api/v5/carts/{cart_uuid}/items/{item_uuid}       → Remove item
PUT    /api/v4/carts/{cart_uuid}/delivery-specification  → Set delivery address
PUT    /api/v5/carts/{cart_uuid}                         → Apply promo code
POST   /api/v5/carts/{cart_uuid}/valid                   → Validate cart
                                                         → then hand off, or create the order

What's Next?