X-Agent-Key: sq_agt_*. Scopes: read_discounts, write_discounts.
A discount has a method (code | automatic), a class (product | order | shipping), a value_type (percentage | fixed_amount) and a value, with optional starts_at/ends_at, usage_limit, once_per_customer, and combines_with.
Endpoints
POST /discounts·GET /discounts?method=&status=&class=(cursor paginated) ·GET /discounts/{id}·PUT /discounts/{id}·DELETE /discounts/{id}POST /discounts/{id}/codes— bulk-add codes to a code discountGET /discounts/lookup?code=SAVE20— resolve a code to its discount
Volume discounts (quantity tiers)
An automatic product discount withapplies_to.quantity_tiers is a volume discount (“Buy 2, get 10% off · Buy 3, get 15% off”). Checkout applies it with no code, on every payment method.
value_typeis one type for every tier:percentage, orfixed_amount= amount off each eligible item.- Scope with
product_idsand/orcollection_ids; with neither, every product is eligible. - The tier is picked by the total quantity of eligible items in the cart; the highest tier reached applies.
- Tiers must be unique, whole quantities, and each higher quantity must give a bigger discount (max 10 tiers). No
usage_limit/once_per_customer. - Combinations: a code stacks only when the code has
combines_with.product_discounts: trueand the volume discount allows the code’s class (order_discounts/shipping_discounts). Otherwise the shopper gets whichever saves more; a code that saves less is refused with a message. - One automatic product discount per cart line (the one that saves the most). Member pricing does not stack with it. It applies to the first payment of a subscription, not renewals.
usage_countcounts the orders it was applied to; a refund releases it.
GET /api/v1/checkout/cart/volume-offers/{store_id}/{product_id} returns the product’s live tiers; POST /api/v1/checkout/validate-coupon with items: [{variantId, quantity}] returns automatic_discounts priced by the same code checkout charges with. Merchant guide: Volume discounts.
Emits discounts/create|update|delete. (Legacy PriceRule is not used — this is the current model.)