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:
- Creates a cart with a first item
- Adds a second item
- Updates the quantity of an item
- Removes an item
- Sets the delivery specification to delivery
- Applies a promo code
- 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?
- Hand off to Blaze checkout → see the Checkout Handoff guide
- Create the order via API (certified partners) → see the Certified Checkout Flow
- Add recommendations → see the Recommendations Flow example
- Full endpoint reference → see the Cart & Checkout guide