Skip to main content

Cart API

The cart API manages the shopping cart for the current session. All cart endpoints are public (__return_true) — the cart is bound to a session token, not a logged-in user.

Session ownership is carried by the server-set wpec_cart_id cookie. You may pass a cart_id as a hint (JSON body, cart_id query param, or X-Cart-ID header), but when it conflicts with the cookie, the cookie wins and the supplied value is ignored (the mismatch is logged, not rejected — a stale client cart_id will not lock a shopper out of their own cart).

Get cart

GET /ec/v1/cart

The response wraps the cart under a cart key:

{
"cart": {
"items": [
{
"id": "cart_item_abc123",
"product_id": 1,
"variant_id": null,
"title": "Product Name",
"price": "29.99",
"quantity": 2,
"total": "59.98",
"image": "https://…"
}
],
"subtotal": "59.98",
"shipping": "5.00",
"tax": "15.60",
"total": "80.58",
"item_count": 2,
"coupons": []
}
}

Add item

POST /ec/v1/cart/items
{
"product_id": 1,
"variant_id": null,
"quantity": 2,
"options": {}
}

product_id is required (400 otherwise); quantity clamps to a minimum of 1. variant_id and options are optional.

caution

Parameter order matters in the PHP service: CartService::addItem($product_id, $variant_id, $quantity, $options) — variant before quantity. Getting this wrong silently adds the wrong quantity/variant.

Update item quantity

PATCH /ec/v1/cart/items/{item_id}
PUT /ec/v1/cart/items/{item_id}
{ "quantity": 3 }

Remove item

DELETE /ec/v1/cart/items/{item_id}

The item id is the cart-item token (e.g. cart_item_abc123) — it goes in the path, not the body.

Clear cart

POST /ec/v1/cart/clear

Shipping on the cart

MethodEndpointBodyPurpose
POST/ec/v1/cart/shipping-address{ "country": "GR", "region": "…", "postcode": "…" }Set the address used to compute shipping (country required)
POST/ec/v1/cart/shipping-method{ "method_id": 12 }Select a shipping method (method_id required)
GET/ec/v1/cart/shipping-methodsAvailable methods with computed cost, returned under methods

Cart summary

GET /ec/v1/cart/summary

A lightweight payload for the mini-cart (counts + totals) without the full item list.

Coupons

Coupons are applied at the coupon endpoints, not on the cart:

POST /ec/v1/coupons/apply
{ "code": "SUMMER2026" }
POST /ec/v1/coupons/remove
{ "code": "SUMMER2026" }
GET /ec/v1/coupons/applied
danger

Use /ec/v1/coupons/apply|remove|appliedNOT /ec/v1/cart/coupons. There is no coupon route under /cart.

JavaScript integration

The cart is returned under a cart key, but some related endpoints wrap differently — normalize defensively:

const response = await fetch('/wp-json/ec/v1/cart');
const data = await response.json();

// Unwrap — GET /cart returns { cart: {...} }; fall back gracefully
const cart = data.cart || data.data || data;

// Normalize field names (snake_case vs camelCase across surfaces)
const itemCount = cart.item_count ?? cart.itemCount ?? 0;

Hooks

HookParametersDescription
wpec_cart_item_price$price, $item, $cartModify an item's price in the cart
wpec_cart_calculated_totals$totals, $cartModify final cart totals

Where to go next