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.
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
| Method | Endpoint | Body | Purpose |
|---|---|---|---|
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-methods | — | Available 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
Use /ec/v1/coupons/apply|remove|applied — NOT /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
| Hook | Parameters | Description |
|---|---|---|
wpec_cart_item_price | $price, $item, $cart | Modify an item's price in the cart |
wpec_cart_calculated_totals | $totals, $cart | Modify final cart totals |
Where to go next
- REST API Overview · Products · Orders
- Authentication — why cart routes are public and how sessions are bound.