Carts & checkout
Guest carts, customer carts, the merge between them, and turning a cart into an order.
Cart lines and items
A cart is a list of lines. Each line targets a product variant and a quantity, plus optional modifiers (e.g. size, add-ons for restaurants):
{ variantId: "var_123", quantity: 2, modifiers: { "grp_size": ["mod_large"] } }Once a line exists, you address it by its line id (cart.items[].id) — not
the variant id — to change quantity or remove it. Adding the same
variant + modifier set again merges into the existing line.
Guest carts vs. customer carts
- A guest cart has no
customerId. Anyone holding its id can read it. - A customer cart belongs to a logged-in shopper. Only that customer can
read it;
cart.me()returns it without needing the id.
When a guest logs in, their guest cart is claimed (merged) into their
customer cart — automatically during auth.verifyOtp if a guest cart id is
known. You can also merge explicitly with cart.claim(cartId).
The SDK manages cart ids for you (Next.js)
With the Next.js adapter, the cart id lives in an httpOnly cookie. You call
storekit.cart.add(item) / setQuantity / remove with no cart id — the
adapter tracks it. The framework-agnostic core client is explicit about cart
ids instead. See SDK — Next.js.
Cart totals
A cart response includes computed money fields as strings (to avoid float rounding):
{
subtotal: "1200.00",
total: "1320.00",
charges: { taxAmount: "120.00", taxInclusive: false, packagingCharge: "0.00",
deliveryCharge: "0.00", deliveryMessage: null, total: "1320.00" },
currency: "INR",
items: [ /* lines */ ],
}Format them for display with formatMoney().
Checkout
Checkout turns the customer's cart into an order and a payment intent. It requires a logged-in customer.
const { data, error } = await storekit.checkout.create({
orderType: "delivery", // or "pickup" | "dine_in"
shipping: { firstName, address, city, state, zipCode, country },
couponCode: "WELCOME10", // optional
notes: "Leave at the door", // optional
});
// data.redirectUrl → hand off to the payment providerBehind the scenes the API:
- Re-checks stock for every line (fails with
INSUFFICIENT_STOCKif something sold out). - Validates the coupon, minimum order value, and delivery serviceability.
- Creates the order in
pendingstatus and a payment intent. - Returns a
redirectUrlto the payment provider.
Idempotency
checkout.create() is idempotent. The SDK generates an idempotency key for
you (or pass your own). Retrying with the same key returns the same pending
order instead of creating duplicates. A key bound to an already-progressed
order fails with STALE_CHECKOUT (410) — start a fresh checkout.
Common checkout errors
| Code | Meaning |
|---|---|
INSUFFICIENT_STOCK | A line went out of stock between cart and checkout. |
MINIMUM_ORDER_NOT_MET | Cart total is below the store's minimum. |
COUPON_EXPIRED / COUPON_INVALID | The coupon can't be applied. |
STALE_CHECKOUT | The idempotency key belongs to a non-pending order. |
PAYMENT_NOT_CONFIGURED | The store hasn't set up payments. |
After the customer pays and returns, you confirm the order — see Payments.