Skip to content
Elara One docs

Carts and the cart token

Create a cart, add and change lines, apply coupons, set addresses and shipping, and read totals, tax, gifts and nudges.

A cart holds what a shopper is about to buy. You create one, get back a cart_token, and send that token as X-Cart-Token on every cart and checkout call. There are no cookies or sessions on the API side: the token is the cart's identity.

The flow

  1. POST /v1/cart creates a cart and returns its cart_token.
  2. POST /v1/cart/lines adds variants. PATCH and DELETE on /v1/cart/lines/{id} change or remove them.
  3. POST /v1/cart/coupon applies a promotion code (optional).
  4. PUT /v1/cart/addresses sets the shipping and billing addresses.
  5. GET /v1/cart/shipping-options lists the delivery and collection options for that address, and PUT /v1/cart/shipping-option picks one.
  6. Checkout takes payment and places the order.

Every write returns the whole cart, recalculated, so you never need a second call to refresh it.

Create a cart

curl -X POST https://api.elaraone.app/api/v1/cart \
  -H "X-Tenant-Key: $ELARAONE_TENANT_KEY" \
  -H "X-Tenant-Secret: $ELARAONE_TENANT_SECRET"
201 Created
{
  "data": {
    "cart_token": "01JB9K3N7Q2W5X8Z4C6V1T0R3M",
    "cart": {
      "id": 812,
      "currency": "GBP",
      "lines": [],
      "sub_total": { "amount": 0, "currency": "GBP", "formatted": "£0.00" },
      "tax_total": { "amount": 0, "currency": "GBP", "formatted": "£0.00" },
      "total": { "amount": 0, "currency": "GBP", "formatted": "£0.00" }
    }
  }
}
  • A cart token lasts 30 days from when it is issued.
  • An unknown or expired token, or the token of a cart that has become an order, returns 404 CART_NOT_FOUND. Create a new cart.
  • Create the cart with a signed-in customer's bearer token and it belongs to that customer. A signed-in customer can also call GET /v1/cart without X-Cart-Token to resume their current cart; the token comes back in the X-Cart-Token response header and in meta.cart_token.
  • Send X-Cart-Token with POST /v1/auth/login or POST /v1/auth/register to merge a guest's cart into the customer's. See customers.

Add a line

Send either a variant_id or a sku, with a quantity of at least 1. Send an Idempotency-Key so a retried request never adds the line twice.

curl -X POST https://api.elaraone.app/api/v1/cart/lines \
  -H "X-Tenant-Key: $ELARAONE_TENANT_KEY" \
  -H "X-Tenant-Secret: $ELARAONE_TENANT_SECRET" \
  -H "X-Cart-Token: $CART_TOKEN" \
  -H "Idempotency-Key: $(uuidgen)" \
  -H "Content-Type: application/json" \
  -d '{ "sku": "MUG-STONE", "quantity": 2 }'

To change the quantity, send PATCH /v1/cart/lines/{id} with { "quantity": 3 }. To remove a line, send DELETE /v1/cart/lines/{id}. Both accept an Idempotency-Key too. The {id} is the line's id from the cart, not the variant's. A line id that is not in this cart returns 404 CART_LINE_NOT_FOUND.

The cart object

FieldMeaning
id, currencyThe cart's id and currency
linesThe lines, described below
shippablefalse when nothing in the cart ships (a digital-only or empty cart), so you can skip the delivery step
addressesshipping and billing addresses
shippingThe chosen option and its sub_total, tax_total, total and breakdown
coupon_code, couponThe code on the cart and its state
discountsEach promotion applied, with its label, kind, amount, and how much came off the items and off the delivery
sub_totalThe lines before promotions
discount_totalWhat promotions took off the lines
shipping_discountWhat promotions took off the delivery, already applied to shipping and total
savings"You saved": the promotion discounts plus the shipping discount
tax_total, tax_breakdown, tax_zoneTax, per rate, and how prices should be labelled. See money.
nudgesMessages that tell the shopper how to qualify for an offer
rewardsFree gifts and "choose a free product" offers the cart has earned
totalWhat the shopper pays

Each line has an id, quantity, variant (id, sku, name), unit_price, sub_total, discount_total, sub_total_discounted, discounts, gift, tax_amount and total.

All amounts are money objects. Show them as they are; do not recompute them.

Coupons

POST /v1/cart/coupon with { "code": "WELCOME10" } applies a code. DELETE /v1/cart/coupon removes it.

A code that cannot go on the cart is refused with 422, and the cart is left exactly as it was:

error.codeWhenerror.details.reason
COUPON_INVALIDNo such codeunknown
COUPON_EXPIREDThe code or its offers have not started yet, or have endednot_started, ended
COUPON_USED_UPThe code has reached its usage limitused_up
COUPON_LIMIT_REACHEDThis customer (or, for a guest, this email) has used it as often as allowedlimit_reached
COUPON_NOT_APPLICABLENothing in this basket qualifiesthreshold, customer, items

For threshold, error.details.remaining is the money still to spend, and error.message says it in words ("Spend £20.00 more to use this code."). Show error.message next to the code field.

A code that was applied can stop qualifying later, for example when the shopper removes items. It stays on the cart, and coupon.status changes from applied to not_applicable, with coupon.reason_code and, for a spend threshold, coupon.remaining.

Addresses

PUT /v1/cart/addresses sets both addresses in one call. billing is required; shipping can be left out for a click-and-collect order, whose shipping address is the collection point. Set billing_same_as_shipping: true to copy the shipping address.

PUT /v1/cart/addresses
{
  "shipping": {
    "first_name": "Grace",
    "last_name": "Hopper",
    "line_one": "12 Mill Lane",
    "city": "York",
    "postcode": "YO1 7HH",
    "country_id": 235,
    "contact_email": "[email protected]",
    "contact_phone": "+447700900123"
  },
  "billing_same_as_shipping": true
}

Address fields are title, first_name, last_name, company_name, line_one, line_two, line_three, city, state, postcode, country_id, delivery_instructions, contact_email and contact_phone. country_id comes from GET /v1/countries.

For a signed-in customer you can send { "address_id": 42 } instead of the fields to use a saved address, or add "save_to_account": true to a new address to save it to their address book once the order is placed. A guest cannot use address_id: it returns 422 ADDRESS_NOT_FOUND.

If a shipping option was already chosen, changing the address re-prices it for the new destination or clears it. meta.shipping_option_cleared tells you which.

Shipping options

GET /v1/cart/shipping-options lists exactly what PUT /v1/cart/shipping-option will accept for the cart's current address. Before a shipping address is set it returns 422 SHIPPING_ADDRESS_REQUIRED.

GET /v1/cart/shipping-options (trimmed)
{
  "data": [
    {
      "identifier": "standard",
      "name": "Standard delivery",
      "description": "2 to 4 working days",
      "price": { "amount": 495, "currency": "GBP", "formatted": "£4.95" },
      "discounted_price": null,
      "collect": false,
      "kind": "delivery",
      "collection_location": null
    }
  ]
}

Pick one with PUT /v1/cart/shipping-option and { "identifier": "standard" }. A click-and-collect option has collect: true and a collection_location with the address and opening hours. discounted_price shows the price after a free-delivery or delivery-discount promotion.

The engine remembers the price you showed. If the merchant changes a rate, or the basket crosses a weight or spend band, before the shopper pays, checkout refuses with 409 SHIPPING_OPTION_CHANGED rather than charge a price the shopper never saw. See checkout.

Gifts, rewards and nudges

Promotions can add to the cart as well as take off it.

  • Free gifts. A gift line has gift: true. Its quantity belongs to the promotion, so PATCH returns 422 GIFT_LINE_LOCKED. The shopper can remove it with DELETE, and it is then not offered again on that cart.
  • "Choose a free product" offers. rewards lists them with type: "choice". Add one of the listed variants or products as a normal line and the promotion makes it free. choose_qty is how many free units the cart has earned and chosen_qty how many are already in it. items gives picker rows when the offer lists specific products.
  • Nudges. Each entry in nudges has a message, such as "Spend £12.00 more for free delivery", and the remaining amount. Show them near the basket total.

Stock

Adding a line checks that the variant can be bought in that quantity, and refuses with 422 VALIDATION_FAILED when it cannot. A cart does not reserve stock: two shoppers can have the last item in their carts at the same time.

Stock is locked when it matters: as the order is placed. Checkout locks the stock of every variant in the cart, checks it again, and takes it off in the same step that creates the order, so the last item can only be sold once. If the stock has gone, checkout returns 422 VALIDATION_FAILED and no order is created.