Cart API
Open a cart, set what is in it, read what it comes to
A cart is where a sale begins. You open one, set quantities on it, and hand it to checkout, which turns it into an order.
Four operations, all under /v1/cart. Every one is scoped to your own
organization: a cart is created, found and amended inside your org's own store, so
a cart id belonging to another tenant is simply not there and reads as 404.
Cart
{
"id": "6QiZNqrY9hW",
"status": "active",
"currency": "usd",
"email": "jane@example.com",
"store": "XkSkQWyr5T3",
"items": [
{
"id": "var_xyz789",
"kind": "variant",
"name": "Premium T-Shirt — Black / M",
"sku": "TEE-BLK-M",
"quantity": 2,
"priceCents": 2999
}
],
"lineTotalCents": 5998,
"discountCents": 0,
"subtotalCents": 5998,
"shippingCents": 0,
"taxCents": 0,
"totalCents": 5998,
"createdAt": "2026-08-05T20:18:13Z",
"updatedAt": "2026-08-05T20:18:13Z"
}Every amount is whole cents, and every field name says so.
status is active while the cart is being filled, ordered once checkout
completed it, discarded if the shopper abandoned it.
shippingCents and taxCents stay 0 until checkout resolves a shipping option
and a tax region. A cart total before checkout is the merchandise total, and
is meant to be.
Open a cart
POST /v1/cart
curl -X POST https://api.hanzo.ai/v1/cart \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"email": "jane@example.com", "currency": "USD"}'| Field | Meaning |
|---|---|
email | The shopper's address, for a cart belonging to someone not signed in. |
user | The signed-in shopper this cart belongs to. Empty means a guest cart. |
store | The storefront being filled. Empty uses your org's default store. |
currency | ISO 4217, lower-cased. Empty means usd. |
Every field is optional — an empty body opens a perfectly good anonymous cart.
Answers 201 with the cart.
currency is a hint, not a commitment: checkout overrides it with the store's
own currency when the sale is authorized.
Read a cart
GET /v1/cart/{id}
curl https://api.hanzo.ai/v1/cart/6QiZNqrY9hW \
-H "Authorization: Bearer $TOKEN"Answers 200 with the cart, or 404 if there is no such cart in your org.
Set an item
POST /v1/cart/{id}/item
This is the one way a cart's contents change. Add, change and remove are the same call at three quantities.
curl -X POST https://api.hanzo.ai/v1/cart/6QiZNqrY9hW/item \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"variant": "TEE-BLK-M", "quantity": 2}'| Field | Meaning |
|---|---|
product | The catalog product to set, by id or URL slug. |
variant | The sellable variant to set, by id or SKU. |
quantity | How many the cart holds after this call. 0 removes the line. |
Name either product or variant, never both. Prefer variant for
anything sold in sizes, colours or tiers — the price and the stock belong to the
variant, so a product-level line on a varianted product prices the wrong thing.
quantity is the result, not a delta. Sending 3 leaves 3 however many were
there before, so a retry is safe and a double-submit cannot double an order.
There is no DELETE. quantity: 0 removes the line; a second spelling of one
act would be a second set of edge cases.
The item's price and name are cached onto the line as it is added, so the cart keeps the price the shopper was shown even if the catalog moves underneath it.
Answers 200 with the whole updated cart. An item that resolves to nothing in the
catalog is 400, and the cart is left exactly as it was — nothing is partially
applied.
Discard a cart
POST /v1/cart/{id}/discard
curl -X POST https://api.hanzo.ai/v1/cart/6QiZNqrY9hW/discard \
-H "Authorization: Bearer $TOKEN"A discarded cart is closed, not deleted: the row stays, so abandoned-basket reporting still has something to read. It stops being a cart anything will check out.
Discarding is idempotent — a cart already discarded answers its stored state rather than failing.
Checkout
A cart becomes an order through the store checkout addresses, which take the storefront in the path:
| Endpoint | What it does |
|---|---|
POST /v1/store/{storeid}/authorize | Hold the funds without settling them. |
POST /v1/store/{storeid}/capture/{orderid} | Settle a previous authorization. |
POST /v1/store/{storeid}/charge | Authorize and capture in one call. |
Errors
| Status | When |
|---|---|
400 | Neither product nor variant named, both named, a negative quantity, or an item that is not in the catalog. |
403 | No validated organization on the call — you are not signed in. |
404 | No such cart in your organization. Another tenant's id reads the same way, so the id space cannot be probed. |
503 | Commerce is not co-resident in this process. |
How is this guide?