Discounts

Create coupon and automatic merchandise discounts, choose who and what qualifies, and control how offers combine.

Discounts let you create coupon codes and automatic merchandise offers for a market. Use the read_markets scope to view discounts and write_markets to create or change them.

The API supports six discount types:

  • percentage reduces eligible merchandise by a percentage.
  • fixed_amount subtracts a currency-specific amount. Provide an amount for the store's base currency and any additional market currencies you support.
  • buy_x_get_y rewards customers when a complete qualifying set is present.
  • bundle applies a fixed price or percentage saving to a complete group of products or variants.
  • free_gift grants gift-only products through gift_mode and gift_items.
  • tiered applies the highest reached subtotal tier, using tier_value_kind and ascending tiers in the base currency.

Fixed savings, including tiers, are capped at the remaining eligible merchandise value. A threshold of 100 with 200 off is valid: at a subtotal of 100 the saving is 100, leaving zero merchandise value, never a negative amount. Tax, shipping and other charges follow their own rules.

Each type accepts the fields described for it below. Value, amounts, Buy X Get Y, bundle and gift fields sent with another type are rejected; tier_value_kind and tiers sent with another type are ignored. The limits endpoint lists the supported values, field limits, and configuration options: GET /markets/{marketId}/discounts/limits.

Discounts are applied to eligible merchandise before tax is calculated. Buy X Get Y, bundle and claimed gift offers use specific cart units, which no other such offer can use. Bundle savings are distributed proportionally across the participating order lines.

When a market allows discounts to combine, Buy X Get Y, bundle and gift offers apply first, then product-targeted offers, then order-wide offers. Each later discount is calculated from the amount remaining on the affected line. Tringify records these allocations in the order's pricing snapshot, so order reads and webhooks preserve the exact savings applied at checkout.

Coupon codes use letters A–Z, digits, hyphens and underscores, are stored in upper case, are unique within a market, and are matched without regard to case. Each discount also has a unique priority position. A discount is stored as active or disabled; active discounts may appear as scheduled, active, or expired according to their start and end dates. Unlimited usage limits are null in responses and webhooks; send -1 or null to set them.

Reading one discount returns its targeting and eligibility IDs; list records leave those arrays empty. Product, variant, collection, category, Buy X Get Y, bundle and gift labels are included when the token has read_products; customer names, email addresses, and customer-group names require read_customers. The can_view_products and can_view_customers fields indicate whether those related labels are available to the current token. Response dates starts_at, ends_at, created_at and updated_at are display strings in the store's time zone; starts_at_iso and ends_at_iso give local store time in the form create and update accept.

Create each discount type#

Percentage#

A coupon that takes 15% off two collections, capped at a maximum saving per currency and limited to one use per customer.

json
// POST /api/2025-01/markets/{marketId}/discounts
{
  "name": "Spring Sale",
  "type": "percentage",
  "activation": "coupon",
  "code": "SPRING15",
  "priority": 10,
  "value": 15,
  "applies_to": "specific_collections",
  "collection_ids": ["11111111-1111-4111-8111-111111111111", "22222222-2222-4222-8222-222222222222"],
  "max_discount": { "USD": "40.00", "EUR": "36.00" },
  "customer_eligibility": "everyone",
  "per_customer_limit": 1,
  "starts_at": "2025-03-01T00:00:00",
  "ends_at": "2025-03-31T23:59:59"
}

Fixed amount#

An automatic offer that subtracts a set amount once the order reaches a minimum subtotal. Include the store's base currency; amounts for other market currencies are optional, and a currency without one uses the base amount converted at the market's rate.

json
// POST /api/2025-01/markets/{marketId}/discounts
{
  "name": "$10 off orders over $75",
  "type": "fixed_amount",
  "activation": "automatic",
  "priority": 20,
  "amounts": { "USD": "10.00", "EUR": "9.00" },
  "applies_to": "entire_order",
  "min_subtotal": { "USD": "75.00", "EUR": "68.00" },
  "exclude_sale_items": true,
  "customer_eligibility": "everyone"
}

Buy X Get Y#

Buy two items from a collection and receive one free. bxgy_buy_items defines what qualifies, bxgy_get_items defines the reward, and bxgy_max_uses caps how many times one order may repeat the offer. Buy and Get independently accept simple products (product), exact variants (variant), collections, and categories; an item qualifies when it matches any target on its side. A variable parent must be expanded to exact variants. Each side may hold up to max_bxgy_items_per_discount targets of any mix of types. Collection and category membership matches the parent of a cart variant. Bought and reward items are always different units, even when the two sides overlap, and the cheapest qualifying items become the rewards, whatever their order in the cart. Rewards apply only when a complete qualifying set is present.

json
// POST /api/2025-01/markets/{marketId}/discounts
{
  "name": "Buy 2 tees, get 1 free",
  "type": "buy_x_get_y",
  "activation": "automatic",
  "priority": 30,
  "bxgy_buy_quantity": 2,
  "bxgy_get_quantity": 1,
  "bxgy_get_type": "free",
  "bxgy_max_uses": 3,
  "bxgy_buy_items": [ { "item_type": "collection", "item_id": "11111111-1111-4111-8111-111111111111" } ],
  "bxgy_get_items": [ { "item_type": "collection", "item_id": "11111111-1111-4111-8111-111111111111" } ],
  "applies_to": "entire_order",
  "customer_eligibility": "everyone"
}

Set bxgy_get_type to percentage or fixed with bxgy_get_value when the reward is reduced rather than free.

json
// BXGY examples: keep the quantities and reward fields above.
// Collection purchase -> exact variant reward
{"bxgy_buy_items":[{"item_type":"collection","item_id":"11111111-1111-4111-8111-111111111111"}],"bxgy_get_items":[{"item_type":"variant","item_id":"1043"}]}
// Exact variant purchase -> category reward
{"bxgy_buy_items":[{"item_type":"variant","item_id":"1043"}],"bxgy_get_items":[{"item_type":"category","item_id":"7"}]}
// Simple product purchase -> exact variant reward
{"bxgy_buy_items":[{"item_type":"product","item_id":"42"}],"bxgy_get_items":[{"item_type":"variant","item_id":"1043"}]}

Bundle#

A bundle prices a specific complete set. Every component must be present at its required quantity. A product component matches any variant of that product; a variant component matches only that variant, and variants may come from different products. Use bundle_value_mode fixed_price with bundle_prices, or percentage with bundle_percentage. Discount reads include a display-only parent_id for each resolved variant component, and its label includes both product and variant names. Do not send parent_id or label in component writes; write only item_type, item_id, and quantity.

json
// POST /api/2025-01/markets/{marketId}/discounts
{
  "name": "Camera starter kit",
  "type": "bundle",
  "activation": "automatic",
  "priority": 40,
  "bundle_value_mode": "fixed_price",
  "bundle_prices": { "USD": "499.00", "EUR": "459.00" },
  "bundle_max_sets": 1,
  "bundle_items": [
    { "item_type": "product", "item_id": "812", "quantity": 1 },
    { "item_type": "variant", "item_id": "1043", "quantity": 1 },
    { "item_type": "product", "item_id": "907", "quantity": 2 }
  ],
  "applies_to": "entire_order",
  "customer_eligibility": "everyone"
}

Free gift#

An automatic offer that lets the shopper claim one exact variant of a gift-only variable product. Use a simple gift-only product without variant_id, or identify an exact variant that belongs to a gift-only variable product.

json
// POST /api/2025-01/markets/{marketId}/discounts
{
  "name": "Choose a free T-shirt",
  "type": "free_gift",
  "activation": "automatic",
  "priority": 50,
  "gift_mode": "offer",
  "gift_items": [
    { "product_id": 42, "variant_id": 4201, "quantity": 1 }
  ],
  "applies_to": "entire_order",
  "customer_eligibility": "everyone"
}

Tiered#

An automatic offer with ascending base-currency subtotal thresholds. Only the highest threshold reached applies, judged on the merchandise subtotal before any discount. A tiered discount also accepts min_subtotal and max_discount, and applies them; it rejects min_quantity.

json
// POST /api/2025-01/markets/{marketId}/discounts
{
  "name": "Spend more, save more",
  "type": "tiered",
  "activation": "automatic",
  "priority": 60,
  "tier_value_kind": "percentage",
  "tiers": [
    { "min_subtotal": "100.00", "value": "10" },
    { "min_subtotal": "200.00", "value": "20" }
  ],
  "applies_to": "entire_order",
  "customer_eligibility": "everyone"
}

Target products and customers#

A percentage, fixed-amount or free gift discount can cover the whole order or selected products, exact variants, collections, or categories; for a free gift, the selection is what the shopper must buy to unlock the gift. With applies_to set to specific_products, use product_ids for simple products or whole variable products and variant_ids for exact variants. A whole variable product includes its current and future variants. You can mix both arrays, but do not include a variable product and one of its child variants in the same discount. The combined product and variant count cannot exceed max_products_per_discount. Eligibility can include everyone, selected customers, or selected customer groups. The detail response always includes the selected ids. Names and labels are included when your token can read the related products or customers.

json
// Percentage off one simple product, every variant of product 812, and one exact variant of another product
{
  "type": "percentage",
  "value": 15,
  "applies_to": "specific_products",
  "product_ids": [42, 812],
  "variant_ids": [1043]
}

Schedule and control usage#

Coupon discounts require a code; automatic discounts apply when the order qualifies and the market's discount settings allow it. Add optional start and end dates, order conditions, total usage limits, and per-customer limits. A use is held when an order is placed and counts toward both limits while the checkout is unpaid; it is given back when the checkout expires unpaid or the order is cancelled, and, if refund_restores_usage is on, shortly after a full refund. A payment that arrives after its checkout expired keeps its use, even past the limit. Customers are recognised by account or by email address, so guest orders count toward that email's per-customer limit and disqualify it from first-order offers. usage_count includes held uses, and usage_held_count says how many are held. Disable an offer to pause it without losing its definition. When enabled, its current status follows its schedule.

Combine offers#

Market discount settings decide how offers combine. With stacking_mode single, one discount applies: every eligible automatic discount and every entered code are ranked together, and the first wins. With stack, every eligible automatic discount applies, plus entered codes in ranked order up to coupon_limit (automatic discounts do not count toward it). priority_mode sets the ranking: best_for_customer by each discount's own saving, manual by priority number, lowest first. Discounts are ranked one by one, not searched for the largest combined saving; when two rank equally, automatic discounts come first. With auto_coupon_combine false, codes apply only when no automatic discount applies; it has no effect in single mode. Buy X Get Y, bundle and claimed gift offers use specific cart units, and two of them cannot use the same units: the higher-ranked keeps them, and an offer that cannot get every unit it needs does not apply at all. Offers apply in three steps: Buy X Get Y, bundle and gift offers; then product, collection and category discounts; then order-wide discounts. Within a step they follow the ranking, and each uses the amount left after the earlier ones. With apply_to_quantity_priced false, items with quantity pricing get no discount and do not count toward minimum spend, minimum quantity or tiers. New settings apply the next time a cart or checkout is priced.

Read applied discounts#

Discounts reduce merchandise before tax is calculated. Orders retain the exact saving allocated to each order item, including free reward lines and proportional bundle savings. Use the order's saved pricing snapshot for reconciliation, refunds, and reporting rather than recalculating an old order from the discount's current definition.

Webhook events#

Endpoints#

Subscribe to these events when your app keeps a local view of discounts or needs to react when an offer changes. Create and update events contain the current discount definition. Delete events contain the id, market, and last known name. Enabling or disabling an offer publishes discounts/update; changing how offers combine publishes discount_settings/update. Requests that make no change do not publish an event.

Discount created

EVENT discounts/create App scope: read_markets Staff permission: markets:write

Subscribe to receive the complete discount definition after a discount is created in a market.

Payload fields

Field Type Description
discount.gift_mode string Selectable in the Payload builder

Whether unlocked gifts are offered to claim (offer) or inserted automatically (auto_add).

discount.gift_items[*].product_id integer Selectable in the Payload builder

The gift-only product id.

discount.gift_items[*].variant_id integer Selectable in the Payload builder

The exact gift variant id for a variable product; omitted for a simple product.

discount.gift_items[*].quantity integer Selectable in the Payload builder

Granted quantity per cart while the offer qualifies.

discount.tier_value_kind string Selectable in the Payload builder

percentage or fixed_amount for tiered discounts.

discount.tiers[*].min_subtotal string Selectable in the Payload builder

Ascending threshold in the store base currency. Only the highest reached tier applies.

discount.tiers[*].value string Selectable in the Payload builder

Percentage or base-currency amount granted by this tier.

discount.id string Always present

The stable discount id.

discount.market_id string Selectable in the Payload builder

The market where this discount is evaluated.

discount.name string Selectable in the Payload builder

The merchant-facing name of the discount.

discount.type string Selectable in the Payload builder

The pricing rule: percentage, fixed amount, Buy X Get Y, bundle, free gift, or tiered.

discount.activation string Selectable in the Payload builder

Whether the discount applies automatically or after a coupon code is entered.

discount.code string Selectable in the Payload builder

The coupon code, or null for an automatic discount.

discount.status string Selectable in the Payload builder

The current effective status after applying the schedule and enabled state.

discount.priority integer Selectable in the Payload builder

The merchant-defined order used when priority decides between competing offers.

discount.value number Selectable in the Payload builder

The percentage value for a percentage discount; null for other types.

discount.amounts object Selectable in the Payload builder

Fixed discount amounts keyed by currency code; empty for other types.

discount.applies_to string Selectable in the Payload builder

The merchandise scope selected by the merchant.

discount.exclude_sale_items boolean Selectable in the Payload builder

Whether items already on sale are excluded.

discount.min_subtotal object Selectable in the Payload builder

The qualifying merchandise subtotal keyed by currency code.

discount.min_quantity integer Selectable in the Payload builder

The minimum qualifying item quantity, or null when unused.

discount.max_discount object Selectable in the Payload builder

The cap on the amount saved, keyed by currency code (percentage, bundle and tiered discounts).

discount.usage_limit integer Selectable in the Payload builder

The total number of uses allowed, or null when unlimited.

discount.per_customer_limit integer Selectable in the Payload builder

The number of uses allowed per customer (recognised by account or email), or null when unlimited.

discount.customer_eligibility string Selectable in the Payload builder

Whether everyone, selected customers, or selected customer groups qualify.

discount.first_order_only boolean Selectable in the Payload builder

Whether only a customer's first paid order qualifies; guests are recognised by email.

discount.refund_restores_usage boolean Selectable in the Payload builder

Whether an order gives its use back to the total and per-customer limits once every item this discount reduced is refunded, including when the whole order is refunded.

discount.show_in_cart boolean Selectable in the Payload builder

Whether an eligible coupon may be surfaced before checkout.

discount.bxgy_buy_quantity integer Selectable in the Payload builder

The quantity required from the Buy X set.

discount.bxgy_get_quantity integer Selectable in the Payload builder

The quantity rewarded from the Get Y set.

discount.bxgy_get_type string Selectable in the Payload builder

Whether reward items are free, reduced by a percentage, or reduced by a fixed amount off each item.

discount.bxgy_get_value number Selectable in the Payload builder

The percentage off, or the fixed base-currency amount off, each reward item; null when rewards are free.

discount.bxgy_max_uses integer Selectable in the Payload builder

The maximum number of complete Buy X Get Y sets per order.

discount.bxgy_buy_items[*].item_type string Selectable in the Payload builder

The kind of Buy X target: simple product, exact variant, collection, or category.

discount.bxgy_buy_items[*].item_id string Selectable in the Payload builder

The id of the Buy X target.

discount.bxgy_get_items[*].item_type string Selectable in the Payload builder

The kind of Get Y target: simple product, exact variant, collection, or category.

discount.bxgy_get_items[*].item_id string Selectable in the Payload builder

The id of the Get Y target.

discount.bundle_value_mode string Selectable in the Payload builder

Whether a complete bundle has a fixed set price or a percentage reduction.

discount.bundle_percentage number Selectable in the Payload builder

The percentage reduction for each complete bundle set.

discount.bundle_prices object Selectable in the Payload builder

The fixed price of one complete bundle keyed by currency code.

discount.bundle_max_sets integer Selectable in the Payload builder

The maximum number of complete bundle sets discounted per order, or null when unlimited.

discount.bundle_items[*].item_type string Selectable in the Payload builder

product (matches any variant of the product) or variant (matches only that variant).

discount.bundle_items[*].item_id string Selectable in the Payload builder

The product or variant id for this component.

discount.bundle_items[*].quantity integer Selectable in the Payload builder

The quantity required in each complete bundle set.

discount.product_ids array Selectable in the Payload builder

Product ids used when the discount targets selected products.

discount.variant_ids array Selectable in the Payload builder

Exact variant ids used when the discount targets selected products or variants.

discount.collection_ids array Selectable in the Payload builder

Collection ids used when the discount targets selected collections.

discount.category_ids array Selectable in the Payload builder

Category ids used when the discount targets selected categories.

discount.customer_ids array Selectable in the Payload builder

Customer ids used when eligibility is limited to selected customers.

discount.group_ids array Selectable in the Payload builder

Customer-group ids used when eligibility is limited to selected groups.

discount.starts_at string Selectable in the Payload builder

The optional start of the discount window, in the store's time zone with its offset.

discount.ends_at string Selectable in the Payload builder

The optional end of the discount window, in the store's time zone with its offset.

discount.created_at string Selectable in the Payload builder

When the discount was created.

discount.updated_at string Selectable in the Payload builder

When the discount last changed.

Get discount limits

GET read_markets

Learn which discount options and limits are available to this store.

The response lists the accepted values and bounds for discount requests: the supported types, targeting and eligibility choices, percentage and priority ranges, relation caps, sort fields, page sizes, and the store's maximum number of discounts. Use list_default_limit for the initial page, page_size_options for page-size choices, list_max_limit as the upper bound for both per_page and bulk selections, and search_max_length for search text. type_capabilities lists which fields each type supports. Limits are store-wide: every market returns the same values, and the market id in the path is not checked. The sample shows current production values; read the response rather than hard-coding them.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

Discount updated

EVENT discounts/update App scope: read_markets Staff permission: markets:write

Subscribe to receive the current discount definition after its offer, targeting, schedule, limits, or enabled state changes.

Payload fields

Field Type Description
discount.gift_mode string Selectable in the Payload builder

Whether unlocked gifts are offered to claim (offer) or inserted automatically (auto_add).

discount.gift_items[*].product_id integer Selectable in the Payload builder

The gift-only product id.

discount.gift_items[*].variant_id integer Selectable in the Payload builder

The exact gift variant id for a variable product; omitted for a simple product.

discount.gift_items[*].quantity integer Selectable in the Payload builder

Granted quantity per cart while the offer qualifies.

discount.tier_value_kind string Selectable in the Payload builder

percentage or fixed_amount for tiered discounts.

discount.tiers[*].min_subtotal string Selectable in the Payload builder

Ascending threshold in the store base currency. Only the highest reached tier applies.

discount.tiers[*].value string Selectable in the Payload builder

Percentage or base-currency amount granted by this tier.

discount.id string Always present

The stable discount id.

discount.market_id string Selectable in the Payload builder

The market where this discount is evaluated.

discount.name string Selectable in the Payload builder

The merchant-facing name of the discount.

discount.type string Selectable in the Payload builder

The pricing rule: percentage, fixed amount, Buy X Get Y, bundle, free gift, or tiered.

discount.activation string Selectable in the Payload builder

Whether the discount applies automatically or after a coupon code is entered.

discount.code string Selectable in the Payload builder

The coupon code, or null for an automatic discount.

discount.status string Selectable in the Payload builder

The current effective status after applying the schedule and enabled state.

discount.priority integer Selectable in the Payload builder

The merchant-defined order used when priority decides between competing offers.

discount.value number Selectable in the Payload builder

The percentage value for a percentage discount; null for other types.

discount.amounts object Selectable in the Payload builder

Fixed discount amounts keyed by currency code; empty for other types.

discount.applies_to string Selectable in the Payload builder

The merchandise scope selected by the merchant.

discount.exclude_sale_items boolean Selectable in the Payload builder

Whether items already on sale are excluded.

discount.min_subtotal object Selectable in the Payload builder

The qualifying merchandise subtotal keyed by currency code.

discount.min_quantity integer Selectable in the Payload builder

The minimum qualifying item quantity, or null when unused.

discount.max_discount object Selectable in the Payload builder

The cap on the amount saved, keyed by currency code (percentage, bundle and tiered discounts).

discount.usage_limit integer Selectable in the Payload builder

The total number of uses allowed, or null when unlimited.

discount.per_customer_limit integer Selectable in the Payload builder

The number of uses allowed per customer (recognised by account or email), or null when unlimited.

discount.customer_eligibility string Selectable in the Payload builder

Whether everyone, selected customers, or selected customer groups qualify.

discount.first_order_only boolean Selectable in the Payload builder

Whether only a customer's first paid order qualifies; guests are recognised by email.

discount.refund_restores_usage boolean Selectable in the Payload builder

Whether an order gives its use back to the total and per-customer limits once every item this discount reduced is refunded, including when the whole order is refunded.

discount.show_in_cart boolean Selectable in the Payload builder

Whether an eligible coupon may be surfaced before checkout.

discount.bxgy_buy_quantity integer Selectable in the Payload builder

The quantity required from the Buy X set.

discount.bxgy_get_quantity integer Selectable in the Payload builder

The quantity rewarded from the Get Y set.

discount.bxgy_get_type string Selectable in the Payload builder

Whether reward items are free, reduced by a percentage, or reduced by a fixed amount off each item.

discount.bxgy_get_value number Selectable in the Payload builder

The percentage off, or the fixed base-currency amount off, each reward item; null when rewards are free.

discount.bxgy_max_uses integer Selectable in the Payload builder

The maximum number of complete Buy X Get Y sets per order.

discount.bxgy_buy_items[*].item_type string Selectable in the Payload builder

The kind of Buy X target: simple product, exact variant, collection, or category.

discount.bxgy_buy_items[*].item_id string Selectable in the Payload builder

The id of the Buy X target.

discount.bxgy_get_items[*].item_type string Selectable in the Payload builder

The kind of Get Y target: simple product, exact variant, collection, or category.

discount.bxgy_get_items[*].item_id string Selectable in the Payload builder

The id of the Get Y target.

discount.bundle_value_mode string Selectable in the Payload builder

Whether a complete bundle has a fixed set price or a percentage reduction.

discount.bundle_percentage number Selectable in the Payload builder

The percentage reduction for each complete bundle set.

discount.bundle_prices object Selectable in the Payload builder

The fixed price of one complete bundle keyed by currency code.

discount.bundle_max_sets integer Selectable in the Payload builder

The maximum number of complete bundle sets discounted per order, or null when unlimited.

discount.bundle_items[*].item_type string Selectable in the Payload builder

product (matches any variant of the product) or variant (matches only that variant).

discount.bundle_items[*].item_id string Selectable in the Payload builder

The product or variant id for this component.

discount.bundle_items[*].quantity integer Selectable in the Payload builder

The quantity required in each complete bundle set.

discount.product_ids array Selectable in the Payload builder

Product ids used when the discount targets selected products.

discount.variant_ids array Selectable in the Payload builder

Exact variant ids used when the discount targets selected products or variants.

discount.collection_ids array Selectable in the Payload builder

Collection ids used when the discount targets selected collections.

discount.category_ids array Selectable in the Payload builder

Category ids used when the discount targets selected categories.

discount.customer_ids array Selectable in the Payload builder

Customer ids used when eligibility is limited to selected customers.

discount.group_ids array Selectable in the Payload builder

Customer-group ids used when eligibility is limited to selected groups.

discount.starts_at string Selectable in the Payload builder

The optional start of the discount window, in the store's time zone with its offset.

discount.ends_at string Selectable in the Payload builder

The optional end of the discount window, in the store's time zone with its offset.

discount.created_at string Selectable in the Payload builder

When the discount was created.

discount.updated_at string Selectable in the Payload builder

When the discount last changed.

List discounts

GET read_markets

Browse the discounts configured for a market.

Use this endpoint for a paginated discount list. You can filter by current status, discount type, or activation method, and search by name or coupon code. Search matches any part of the name or code, ignoring case. List records carry the discount definition plus worded labels (status_label, type_label, value_label, usage_summary and others); their targeting, eligibility, Buy X Get Y, bundle and gift arrays are always empty and can_view_products/can_view_customers are false. Read one discount to get those. Scheduled and expired statuses are calculated from the discount's dates when you read it. A per_page above list_max_limit is reduced to it, and sorting by ends_at lists discounts without an end date last.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789

Query parameters

Name Type Description
page integer

The page to return, starting at 1.

Example: 1
per_page integer

The number of discounts to return on each page.

Example: 20
status string

Return only active, scheduled, expired, or disabled discounts. Scheduled and expired values are derived from the current time.

Example: active
type string

Filter by type: percentage, fixed_amount, buy_x_get_y, bundle, free_gift, or tiered.

Example: percentage
activation string

Return coupon discounts or automatic discounts.

Example: coupon
search string

Search by discount name or coupon code.

Example: summer
sort_by string

Sort by priority, name, type, activation, usage_count, ends_at, created_at, or updated_at. Defaults to priority. With ends_at, discounts without an end date sort last in either direction.

Example: priority
sort_direction string

Sort in ascending (asc) or descending (desc) order.

Example: asc

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

  • 400 MARKET_DISCOUNT_FILTER_INVALID

    Status/type/activation filter is not a supported value.

  • 400 MARKET_DISCOUNT_SEARCH_TOO_LONG

    Search query exceeds the discount limits max length.

  • 400 MARKET_DISCOUNT_LIST_INVALID_SORT_BY

    Sort_by is not a discount sort column.

  • 400 MARKET_DISCOUNT_LIST_INVALID_SORT_DIRECTION

    Sort_direction is not asc or desc.

  • 404 MARKET_NOT_FOUND

    Market does not exist in this store.

Create a discount

POST write_markets

Add a merchandise discount to a market.

Choose one discount type and provide the fields for that type. value, amounts, Buy X Get Y, bundle and gift fields sent for another type are rejected; tier_value_kind and tiers sent for a type other than tiered are ignored, and so are unknown fields. Empty money maps ({}) are treated as not set, so money maps from a GET can be sent back unchanged for any type. Percentage discounts use value; fixed-amount discounts use amounts; Buy X Get Y offers define qualifying and reward sets; bundles define every required component and either a set price or percentage reduction. Free gifts specify gift-only products and how they enter the cart; tiered discounts specify ascending base-currency subtotal thresholds and apply only the highest reached tier. Coupon discounts need a code that is unique within the market, while automatic discounts apply without one. Product, collection, category, customer, and group ids must belong to the same store. Free delivery is configured with the market's shipping methods. The response is the saved discount, with usage_count and usage_held_count at 0 and a matching usage_summary. A successful create publishes discounts/create.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Body parameters

Name Type Description
name required string

A name merchants can recognize when managing the discount.

Example: Summer sale
type required string

Choose percentage, fixed_amount, buy_x_get_y, bundle, free_gift, or tiered.

Example: percentage
gift_mode string|null

For free_gift: offer or auto_add. On create, omitted or null means offer; on update, omitted or null keeps the current mode. With best_for_customer ranking a gift ranks at its full value (each gift's quantity-specific unit price times its granted quantity) whether or not it is in the cart yet, including advertised coupons before entry. Gift-only units never qualify for other discounts or inflate their ranking. A gift grant is eligible only when its complete set is channel-available, priced, within quantity limits and in stock alongside all physical merchandise, including quantity-priced items excluded from discounts. Stacked gift sets share stock in ranking order; a set is granted only if its complete demand fits after higher-ranked gifts. When automatic discounts and codes don't combine, an offer the shopper hasn't claimed doesn't keep codes out; a code that applies withdraws the offer.

Example: offer
gift_items array<object>

For free_gift: a gift-only product_id, positive quantity per cart, and optional variant_id. Omit variant_id for a simple product; a variable product requires the exact variant_id that belongs to it.

Example: [{"product_id":42,"variant_id":4201,"quantity":1}]
tier_value_kind string|null

For tiered: percentage or fixed_amount.

Example: percentage
tiers array<object>

For tiered: 1–10 tiers with strictly ascending min_subtotal thresholds from 0 to money_amount_max, and positive values, in the base currency and its precision. Only the highest reached tier applies, chosen from the merchandise subtotal before any discount. Percentage values cannot exceed 100. Fixed savings can exceed the threshold but are capped at remaining eligible merchandise at checkout; merchandise never becomes negative. Other markets use the base amounts converted at the market's rate.

Example: [{"min_subtotal":"100","value":"10"},{"min_subtotal":"200","value":"20"}]
activation required string

Use coupon when a shopper enters a code, or automatic when qualifying orders should receive the discount automatically.

Example: coupon
code string

Required for coupon activation. Use letters A–Z, digits, hyphens and underscores, up to code_max_length characters; the code is stored in upper case. Codes are unique within the market and matched without regard to case.

Example: SUMMER20
priority integer

The discount's position when manual priority decides between competing offers. Omission uses 0 on both create and full replacement, which can conflict with another discount at that priority. Send an explicit unique whole number from priority_min through max_priority in the limits response.

Example: 10
value number

The percentage reduction for a percentage discount. It must be greater than percentage_min_exclusive, no more than percentage_max, and use no more than percentage_decimal_places from the limits response.

Example: 20
amounts object

Fixed discount amounts keyed by currency code. Include the store's base currency; additional entries must be currencies enabled for the market. Each amount must be greater than 0, at most money_amount_max, and fit that currency's minor-unit precision. A market currency without its own amount uses the base amount converted at the market's rate.

Example: {"USD": "10.00", "EUR": "8.50"}
applies_to required string

Apply the discount to the whole order or to selected products or variants, collections, or categories. Buy X Get Y and bundle offers define their items separately and use entire_order here.

Example: entire_order
product_ids array<integer>

Products to discount when applies_to is specific_products. A variable product target includes all of its current and future variants.

Example: [12, 34]
variant_ids array<integer>

Exact variants to discount when applies_to is specific_products. You may combine these with simple or whole-variable product targets, up to max_products_per_discount targets in total.

Example: [45, 46]
collection_ids array<string>

The collections to discount when applies_to is specific_collections.

Example: ["11111111-1111-4111-8111-111111111111"]
category_ids array<integer>

The categories to discount when applies_to is specific_categories.

Example: [7]
customer_eligibility required string

Make the discount available to everyone, selected customers, or selected customer groups.

Example: everyone
customer_ids array<string>

The customers who qualify when eligibility is specific_customers.

Example: ["5b2e8c1d-3f4a-4b6c-9d7e-8f9a0b1c2d3e"]
group_ids array<string>

The customer groups that qualify when eligibility is specific_segments.

Example: ["6c3f9d2e-4a5b-4c7d-8e9f-0a1b2c3d4e5f"]
exclude_sale_items boolean

Skip items already on sale. Only percentage and fixed-amount discounts accept true; other types reject it with DISCOUNT_TARGETS_FORBIDDEN.

Example: false
min_subtotal object

Require a minimum merchandise subtotal, keyed by currency code. Include the base currency when you set this condition; other market currencies without an entry use the converted base amount. It is checked before any discount. For percentage, fixed-amount and free gift discounts it counts only the items matched by applies_to, leaving out items excluded by exclude_sale_items and a free gift's own gift items. Buy X Get Y, bundle and tiered discounts use entire_order, so it counts every item in the cart, not only the Buy X, Get Y or bundle items. Gift-only items and items left out by the market's quantity-pricing setting never count. Every type accepts it.

Example: {"USD": "50.00"}
min_quantity integer

Require between quantity_min and min_quantity_max eligible items from the limits response. Percentage, fixed-amount and free gift discounts accept this condition; Buy X Get Y, bundle and tiered discounts reject it with DISCOUNT_MIN_QUANTITY_FORBIDDEN.

Example: 2
max_discount object

Cap the amount saved, keyed by currency code. Percentage, bundle and tiered discounts accept it; fixed-amount, Buy X Get Y and free gift discounts reject it with DISCOUNT_MAX_DISCOUNT_FORBIDDEN.

Example: {"USD": "100.00"}
starts_at string

Start the discount at this local store time, formatted as YYYY-MM-DDTHH:mm:ss.

Example: 2026-08-01T00:00:00
ends_at string

Stop the discount at this local store time. It must be later than starts_at.

Example: 2026-08-31T23:59:59
usage_limit integer

The total number of uses allowed. Send unlimited_sentinel (-1) or null for no limit, or a whole number from quantity_min through max_usage_limit in the limits response; an unlimited discount is returned as null. A use is held when an order is placed and counts toward the limit while the checkout is unpaid, so new orders are refused with DISCOUNT_USAGE_EXHAUSTED once the limit is reached. The use is given back if the checkout expires unpaid or the order is cancelled. A payment that arrives after its checkout expired still keeps its use, which can take the count past the limit. A discount with no usage_limit and no per_customer_limit counts no uses.

Example: -1
per_customer_limit integer

The number of uses allowed for each customer. Send unlimited_sentinel (-1) or null for no limit, or a whole number from quantity_min through max_per_customer_limit in the limits response; an unlimited discount is returned as null. A customer is recognised by account or by email address, ignoring case, so guest orders count toward that email's limit; an order with neither is not checked. Orders over the limit are refused with DISCOUNT_CUSTOMER_LIMIT_REACHED.

Example: 1
refund_restores_usage boolean

Give a use back to usage_limit and per_customer_limit when every item this discount reduced on an order is refunded, or the whole order is refunded. The use is returned shortly after the refund, following the setting the discount has at that moment. The release is final for that order and discount: payment capture or retry cannot reclaim it.

Example: false
first_order_only boolean

Restrict to a customer's first order. Earlier paid, cash-on-delivery or refunded orders under the same account or the same email address (ignoring case) disqualify; test and cancelled orders do not. Guests are recognised by email. An order with neither an account nor an email does not qualify.

Example: false
show_in_cart boolean

Allow the storefront to show this coupon before checkout. Coupon discounts only; sending true for an automatic discount returns DISCOUNT_TARGETS_FORBIDDEN.

Example: false
bxgy_buy_quantity integer

The quantity a shopper must add from the Buy X set.

Example: 2
bxgy_get_quantity integer

The quantity rewarded from the Get Y set.

Example: 1
bxgy_get_type string

Make reward items free, reduce their remaining value by a percentage, or deduct a fixed amount from each reward item. The cheapest qualifying items are the rewards, whatever their order in the cart.

Example: free
bxgy_get_value number

The percentage off each reward item, or the fixed amount deducted from each reward item in the store base currency, converted to the order currency at the market's exchange rate. Fixed means an amount off, not a final selling price. The deduction is capped at the remaining reward-item value. Omit this field when rewards are free. Fixed amounts use the base currency precision and the live money_amount_max.

Example: 50
bxgy_max_uses integer

The maximum number of complete Buy X Get Y sets that may apply to one order: a whole number from bxgy_max_uses_min through bxgy_max_uses_max in the limits response. Omit it or send null for no per-order cap; unlimited_sentinel (-1) is not accepted here.

Example: 1
bxgy_buy_items array<object>

Simple products, exact variants, collections, or categories that can satisfy Buy X. Each item contains item_type (product, variant, collection, category) and string item_id. An item qualifies when it matches any target in the list. Bought and reward items are always different units, even when the two lists overlap.

Example: [{"item_type": "product", "item_id": "12"}]
bxgy_get_items array<object>

Simple products, exact variants, collections, or categories that can be rewarded as Get Y, independently of Buy X targets. The shopper adds reward items to the cart; the discount never adds them. Whole variable products cannot be saved as product targets; select their exact variants.

Example: [{"item_type": "product", "item_id": "34"}]
bundle_value_mode string

Use fixed_price for a set price or percentage for a percentage reduction on each complete bundle.

Example: fixed_price
bundle_prices object

The price of one complete bundle, keyed by currency code. Include the base currency for fixed-price bundles; other market currencies without an entry use the converted base price.

Example: {"USD": "75.00"}
bundle_percentage number

The percentage reduction for each complete bundle when the value mode is percentage.

Example: 15
bundle_max_sets integer

The maximum number of complete bundle sets discounted on one order. Send -1 or null for no limit; an unlimited bundle is returned as null.

Example: 2
bundle_items array<object>

The products or variants and quantities required for one complete bundle. Provide between bundle_components_min and bundle_components_max different components. A product component matches any variant of that product; a variant component matches only that variant.

Example: [{"item_type": "product", "item_id": "12", "quantity": 1}, {"item_type": "variant", "item_id": "45", "quantity": 2}]

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

  • 400 DISCOUNT_NAME_REQUIRED

    Name is empty after trimming.

  • 400 DISCOUNT_NAME_TOO_LONG

    Name is longer than name_max_length.

  • 400 DISCOUNT_TYPE_INVALID

    Type is not a supported discount type.

  • 400 DISCOUNT_ACTIVATION_INVALID

    Activation is not coupon or automatic.

  • 400 DISCOUNT_CODE_REQUIRED

    A coupon discount has no code.

  • 400 DISCOUNT_CODE_AUTOMATIC_FORBIDDEN

    An automatic discount was sent a code.

  • 400 DISCOUNT_CODE_TOO_LONG

    The code is longer than code_max_length.

  • 400 DISCOUNT_CODE_CHARACTERS

    The code uses a character other than A–Z, digits, hyphen or underscore.

  • 400 DISCOUNT_PRIORITY_RANGE

    Priority is outside priority_min to max_priority.

  • 400 DISCOUNT_VALUE_RANGE

    A percentage value is not above 0 and at most 100.

  • 400 DISCOUNT_PERCENTAGE_TOO_PRECISE

    A percentage has more than percentage_decimal_places decimal places.

  • 400 DISCOUNT_VALUE_FORBIDDEN

    Value was sent for a type that does not take one.

  • 400 DISCOUNT_AMOUNTS_REQUIRED

    A fixed-amount discount has no amounts.

  • 400 DISCOUNT_AMOUNTS_FORBIDDEN

    Amounts were sent for a type that does not take them.

  • 400 DISCOUNT_CURRENCY_BASE_REQUIRED

    A money map is missing the store's base currency.

  • 400 DISCOUNT_CURRENCY_INVALID

    A money map uses a currency not assigned to the market.

  • 400 DISCOUNT_CURRENCY_VALUE_RANGE

    A money value is not greater than 0.

  • 400 DISCOUNT_CURRENCY_VALUE_TOO_LARGE

    A money value is above money_amount_max.

  • 400 DISCOUNT_CURRENCY_VALUE_TOO_PRECISE

    A money value, fixed Buy X Get Y value, tier threshold or fixed tier value has more decimal places than its currency.

  • 400 DISCOUNT_APPLIES_TO_INVALID

    Applies_to is not a supported value.

  • 400 DISCOUNT_ENTIRE_ORDER_ONLY

    A Buy X Get Y, bundle or tiered discount was not set to entire_order.

  • 400 DISCOUNT_ELIGIBILITY_INVALID

    Customer_eligibility is not a supported value.

  • 400 DISCOUNT_TARGETS_REQUIRED

    Specific targeting or eligibility was chosen without its id list, or a referenced id is malformed, does not exist, or belongs to another store.

  • 400 DISCOUNT_TARGETS_FORBIDDEN

    An id list was sent that does not match the targeting or eligibility, exclude_sale_items or show_in_cart was set where it is not supported, or a Buy X Get Y item has an unsupported item_type.

  • 400 DISCOUNT_MIN_QUANTITY_FORBIDDEN

    Min_quantity was sent for Buy X Get Y, bundle or tiered.

  • 400 DISCOUNT_MIN_QUANTITY_RANGE

    Min_quantity is below quantity_min.

  • 400 DISCOUNT_MIN_QUANTITY_TOO_LARGE

    Min_quantity is above min_quantity_max.

  • 400 DISCOUNT_MAX_DISCOUNT_FORBIDDEN

    Max_discount was sent for fixed-amount, Buy X Get Y or free gift.

  • 400 DISCOUNT_USAGE_LIMIT_RANGE

    Usage_limit is not -1, null, or within quantity_min to max_usage_limit.

  • 400 DISCOUNT_PER_CUSTOMER_RANGE

    Per_customer_limit is not -1, null, or within quantity_min to max_per_customer_limit.

  • 400 DISCOUNT_DATE_INVALID

    Starts_at or ends_at is not in YYYY-MM-DDTHH:mm:ss form.

  • 400 MARKET_DISCOUNT_DATE_INVALID

    Ends_at is not after starts_at.

  • 400 DISCOUNT_BXGY_FIELDS_FORBIDDEN

    Buy X Get Y fields were sent for another type.

  • 400 DISCOUNT_BXGY_BUY_REQUIRED

    Buy X Get Y has no valid buy items.

  • 400 DISCOUNT_BXGY_GET_REQUIRED

    Buy X Get Y has no valid reward items.

  • 400 DISCOUNT_BXGY_QUANTITY_RANGE

    A buy or reward quantity is outside 1 to max_bxgy_quantity.

  • 400 DISCOUNT_GET_TYPE_REQUIRED

    Buy X Get Y has no bxgy_get_type.

  • 400 DISCOUNT_GET_TYPE_INVALID

    Bxgy_get_type is not free, percentage or fixed.

  • 400 DISCOUNT_GET_VALUE_FORBIDDEN

    Bxgy_get_value was sent for free rewards.

  • 400 DISCOUNT_GET_VALUE_RANGE

    A percentage reward is not above 0 and at most 100.

  • 400 DISCOUNT_GET_VALUE_POSITIVE

    A fixed reward amount is not greater than 0.

  • 400 DISCOUNT_GET_VALUE_TOO_LARGE

    A fixed reward amount is above money_amount_max.

  • 400 DISCOUNT_MAX_USES_PER_ORDER_RANGE

    Bxgy_max_uses is below bxgy_max_uses_min.

  • 400 DISCOUNT_MAX_USES_PER_ORDER_TOO_LARGE

    Bxgy_max_uses is above bxgy_max_uses_max.

  • 400 DISCOUNT_BUNDLE_FIELDS_FORBIDDEN

    Bundle fields were sent for another type.

  • 400 DISCOUNT_BUNDLE_MODE_REQUIRED

    A bundle has no bundle_value_mode.

  • 400 DISCOUNT_BUNDLE_MODE_INVALID

    Bundle_value_mode is not fixed_price or percentage, the other mode's field was also sent (bundle_percentage with fixed_price, or bundle_prices with percentage), or a component's item_type is not product or variant.

  • 400 DISCOUNT_BUNDLE_PRICE_REQUIRED

    A fixed-price bundle has no bundle_prices.

  • 400 DISCOUNT_BUNDLE_PERCENT_REQUIRED

    A percentage bundle has no valid bundle_percentage.

  • 400 DISCOUNT_BUNDLE_ITEMS_RANGE

    The number of components is outside bundle_components_min to bundle_components_max, or a component has a blank item_id.

  • 400 DISCOUNT_BUNDLE_ITEM_DUPLICATE

    The same product or variant appears twice in the bundle.

  • 400 DISCOUNT_BUNDLE_ITEM_QUANTITY

    A component quantity is outside 1 to bundle_item_quantity_max.

  • 400 DISCOUNT_BUNDLE_MAX_SETS_RANGE

    Bundle_max_sets is not -1, null, or within bundle_max_sets_min to bundle_max_sets_max.

  • 400 DISCOUNT_GIFT_FIELDS_FORBIDDEN

    Gift fields were sent for another type.

  • 400 DISCOUNT_GIFT_MODE_INVALID

    Gift_mode is not offer or auto_add.

  • 400 DISCOUNT_GIFT_ITEMS_RANGE

    The number of gift items is outside gift_items_min to gift_items_max.

  • 400 DISCOUNT_GIFT_ITEM_DUPLICATE

    The same gift product or variant appears twice.

  • 400 DISCOUNT_GIFT_ITEM_QUANTITY

    A gift quantity is outside 1 to gift_item_quantity_max.

  • 400 DISCOUNT_GIFT_NOT_GIFT_ONLY

    A gift product_id is not positive, does not exist in the store, or is not marked gift-only.

  • 400 DISCOUNT_GIFT_VARIANT_REQUIRED

    A variable gift product has no variant_id.

  • 400 DISCOUNT_GIFT_VARIANT_INVALID

    The gift variant does not exist, belongs to another product, or was sent for a simple product.

  • 400 DISCOUNT_TIERS_COUNT

    The number of tiers is outside tiers_min to tiers_max.

  • 400 DISCOUNT_TIER_THRESHOLD_INVALID

    A tier threshold is negative or above money_amount_max. A threshold with more decimal places than the base currency returns DISCOUNT_CURRENCY_VALUE_TOO_PRECISE instead.

  • 400 DISCOUNT_TIER_THRESHOLD_ORDER

    Tier thresholds do not strictly increase.

  • 400 DISCOUNT_TIER_VALUE_INVALID

    A tier value is not positive, a percentage is above 100, or an amount is out of range.

  • 400 MARKET_DISCOUNT_RELATION_LIMIT_REACHED

    An id list is longer than its max_*_per_discount limit.

  • 400 MARKET_DISCOUNT_RELATION_DUPLICATE

    An id appears twice in a targeting, eligibility or Buy X Get Y list, or a product is targeted together with one of its own variants.

  • 400 MARKET_DISCOUNT_LIMIT_REACHED

    The market already has max_per_market discounts.

  • 400 STORE_API_INVALID_REQUEST_BODY

    The body is not valid JSON, or is not a JSON object.

  • 400 INVALID_INPUT

    A field has the wrong JSON type, for example a string where a number is expected.

  • 404 MARKET_NOT_FOUND

    Market does not exist in this store.

  • 409 MARKET_DISCOUNT_CODE_DUPLICATE

    Another discount in the market has this code, ignoring case.

  • 409 MARKET_DISCOUNT_PRIORITY_DUPLICATE

    Another discount in the market has this priority.

Discount deleted

EVENT discounts/delete App scope: read_markets Staff permission: markets:write

Subscribe to remove a deleted discount from your integration. The payload keeps its id, market id, and last known name.

Payload fields

Field Type Description
id string Always present

The stable id of the deleted discount.

market_id string Selectable in the Payload builder

The market that owned the discount.

name string Selectable in the Payload builder

The discount name at the time it was deleted.

Discount settings updated

EVENT discount_settings/update App scope: read_markets Staff permission: markets:write

Subscribe when your app needs the current rules for combining discounts in a market.

Payload fields

Field Type Description
discount_settings.market_id string Always present

The market whose combination settings changed.

discount_settings.stacking_mode string Selectable in the Payload builder

single applies one discount per order, chosen by priority_mode; stack applies every eligible automatic discount plus codes up to coupon_limit.

discount_settings.priority_mode string Selectable in the Payload builder

How discounts are ranked: best_for_customer by each discount's own saving, manual by priority number, lowest first. The ranking picks the single discount, fills the coupon limit, and decides which offer keeps items two offers both need.

discount_settings.coupon_limit integer Selectable in the Payload builder

The maximum number of codes that can apply to one order in stack mode. Automatic discounts do not count.

discount_settings.auto_coupon_combine boolean Selectable in the Payload builder

In stack mode, true lets codes apply alongside automatic discounts; false lets codes apply only when no automatic discount applies. No effect in single mode.

discount_settings.apply_to_quantity_priced boolean Selectable in the Payload builder

When false, items with quantity pricing get no discount and do not count toward minimum spend, minimum quantity or tiers.

Get a discount

GET read_markets

Read one discount and its targeting choices.

The response includes the complete discount definition and the ids it targets. Product-facing labels (products, variants, collections, categories, Buy X Get Y, bundle and gift items) are included when your token has read_products; customer names and group labels are included with read_customers. The ids remain available without those additional scopes, and can_view_products and can_view_customers tell you whether labels were included. The returned status reflects the discount's current schedule. usage_count includes uses held by unpaid checkouts; usage_held_count says how many of them are held, and usage_summary words both. Uses are counted only while the discount has a usage_limit or a per_customer_limit: with neither, orders record no use, usage_count doesn't change and usage_summary says uses are not counted. Adding a limit later counts uses from then on. starts_at, ends_at, created_at and updated_at are display strings in the store's time zone; starts_at_iso and ends_at_iso give the start and end as local store time in the YYYY-MM-DDTHH:mm:ss form that create and update accept.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789
discountId required string

Discount id.

Example: 7c4b1e2f-9a8d-4c3b-b2a1-0f9e8d7c6b5a

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

  • 404 MARKET_NOT_FOUND

    Market does not exist in this store.

  • 404 MARKET_DISCOUNT_NOT_FOUND

    Discount does not exist in this market.

Update a discount

PUT write_markets

Replace the editable definition of a discount.

Send the complete definition you want to keep, including all targeting and eligibility lists; read them with GET first, because list records leave them empty. The same type-specific rules used during creation apply here. Updating a disabled discount does not enable it; use the enable endpoint when it is ready to run again. Sending an unchanged definition leaves the discount untouched and publishes no webhook. A successful change publishes discounts/update. The response is the saved discount with its current usage_count, usage_held_count and usage_summary.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789
discountId required string

Discount id.

Example: 7c4b1e2f-9a8d-4c3b-b2a1-0f9e8d7c6b5a

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Body parameters

Name Type Description
name required string

A name merchants can recognize when managing the discount.

Example: Summer sale
type required string

Choose percentage, fixed_amount, buy_x_get_y, bundle, free_gift, or tiered.

Example: percentage
gift_mode string|null

For free_gift: offer or auto_add. On create, omitted or null means offer; on update, omitted or null keeps the current mode. With best_for_customer ranking a gift ranks at its full value (each gift's quantity-specific unit price times its granted quantity) whether or not it is in the cart yet, including advertised coupons before entry. Gift-only units never qualify for other discounts or inflate their ranking. A gift grant is eligible only when its complete set is channel-available, priced, within quantity limits and in stock alongside all physical merchandise, including quantity-priced items excluded from discounts. Stacked gift sets share stock in ranking order; a set is granted only if its complete demand fits after higher-ranked gifts. When automatic discounts and codes don't combine, an offer the shopper hasn't claimed doesn't keep codes out; a code that applies withdraws the offer.

Example: offer
gift_items array<object>

For free_gift: a gift-only product_id, positive quantity per cart, and optional variant_id. Omit variant_id for a simple product; a variable product requires the exact variant_id that belongs to it.

Example: [{"product_id":42,"variant_id":4201,"quantity":1}]
tier_value_kind string|null

For tiered: percentage or fixed_amount.

Example: percentage
tiers array<object>

For tiered: 1–10 tiers with strictly ascending min_subtotal thresholds from 0 to money_amount_max, and positive values, in the base currency and its precision. Only the highest reached tier applies, chosen from the merchandise subtotal before any discount. Percentage values cannot exceed 100. Fixed savings can exceed the threshold but are capped at remaining eligible merchandise at checkout; merchandise never becomes negative. Other markets use the base amounts converted at the market's rate.

Example: [{"min_subtotal":"100","value":"10"},{"min_subtotal":"200","value":"20"}]
activation required string

Use coupon when a shopper enters a code, or automatic when qualifying orders should receive the discount automatically.

Example: coupon
code string

Required for coupon activation. Use letters A–Z, digits, hyphens and underscores, up to code_max_length characters; the code is stored in upper case. Codes are unique within the market and matched without regard to case.

Example: SUMMER20
priority integer

The discount's position when manual priority decides between competing offers. Omission uses 0 on both create and full replacement, which can conflict with another discount at that priority. Send an explicit unique whole number from priority_min through max_priority in the limits response.

Example: 10
value number

The percentage reduction for a percentage discount. It must be greater than percentage_min_exclusive, no more than percentage_max, and use no more than percentage_decimal_places from the limits response.

Example: 20
amounts object

Fixed discount amounts keyed by currency code. Include the store's base currency; additional entries must be currencies enabled for the market. Each amount must be greater than 0, at most money_amount_max, and fit that currency's minor-unit precision. A market currency without its own amount uses the base amount converted at the market's rate.

Example: {"USD": "10.00", "EUR": "8.50"}
applies_to required string

Apply the discount to the whole order or to selected products or variants, collections, or categories. Buy X Get Y and bundle offers define their items separately and use entire_order here.

Example: entire_order
product_ids array<integer>

Products to discount when applies_to is specific_products. A variable product target includes all of its current and future variants.

Example: [12, 34]
variant_ids array<integer>

Exact variants to discount when applies_to is specific_products. You may combine these with simple or whole-variable product targets, up to max_products_per_discount targets in total.

Example: [45, 46]
collection_ids array<string>

The collections to discount when applies_to is specific_collections.

Example: ["11111111-1111-4111-8111-111111111111"]
category_ids array<integer>

The categories to discount when applies_to is specific_categories.

Example: [7]
customer_eligibility required string

Make the discount available to everyone, selected customers, or selected customer groups.

Example: everyone
customer_ids array<string>

The customers who qualify when eligibility is specific_customers.

Example: ["5b2e8c1d-3f4a-4b6c-9d7e-8f9a0b1c2d3e"]
group_ids array<string>

The customer groups that qualify when eligibility is specific_segments.

Example: ["6c3f9d2e-4a5b-4c7d-8e9f-0a1b2c3d4e5f"]
exclude_sale_items boolean

Skip items already on sale. Only percentage and fixed-amount discounts accept true; other types reject it with DISCOUNT_TARGETS_FORBIDDEN.

Example: false
min_subtotal object

Require a minimum merchandise subtotal, keyed by currency code. Include the base currency when you set this condition; other market currencies without an entry use the converted base amount. It is checked before any discount. For percentage, fixed-amount and free gift discounts it counts only the items matched by applies_to, leaving out items excluded by exclude_sale_items and a free gift's own gift items. Buy X Get Y, bundle and tiered discounts use entire_order, so it counts every item in the cart, not only the Buy X, Get Y or bundle items. Gift-only items and items left out by the market's quantity-pricing setting never count. Every type accepts it.

Example: {"USD": "50.00"}
min_quantity integer

Require between quantity_min and min_quantity_max eligible items from the limits response. Percentage, fixed-amount and free gift discounts accept this condition; Buy X Get Y, bundle and tiered discounts reject it with DISCOUNT_MIN_QUANTITY_FORBIDDEN.

Example: 2
max_discount object

Cap the amount saved, keyed by currency code. Percentage, bundle and tiered discounts accept it; fixed-amount, Buy X Get Y and free gift discounts reject it with DISCOUNT_MAX_DISCOUNT_FORBIDDEN.

Example: {"USD": "100.00"}
starts_at string

Start the discount at this local store time, formatted as YYYY-MM-DDTHH:mm:ss.

Example: 2026-08-01T00:00:00
ends_at string

Stop the discount at this local store time. It must be later than starts_at.

Example: 2026-08-31T23:59:59
usage_limit integer

The total number of uses allowed. Send unlimited_sentinel (-1) or null for no limit, or a whole number from quantity_min through max_usage_limit in the limits response; an unlimited discount is returned as null. A use is held when an order is placed and counts toward the limit while the checkout is unpaid, so new orders are refused with DISCOUNT_USAGE_EXHAUSTED once the limit is reached. The use is given back if the checkout expires unpaid or the order is cancelled. A payment that arrives after its checkout expired still keeps its use, which can take the count past the limit. A discount with no usage_limit and no per_customer_limit counts no uses.

Example: -1
per_customer_limit integer

The number of uses allowed for each customer. Send unlimited_sentinel (-1) or null for no limit, or a whole number from quantity_min through max_per_customer_limit in the limits response; an unlimited discount is returned as null. A customer is recognised by account or by email address, ignoring case, so guest orders count toward that email's limit; an order with neither is not checked. Orders over the limit are refused with DISCOUNT_CUSTOMER_LIMIT_REACHED.

Example: 1
refund_restores_usage boolean

Give a use back to usage_limit and per_customer_limit when every item this discount reduced on an order is refunded, or the whole order is refunded. The use is returned shortly after the refund, following the setting the discount has at that moment. The release is final for that order and discount: payment capture or retry cannot reclaim it.

Example: false
first_order_only boolean

Restrict to a customer's first order. Earlier paid, cash-on-delivery or refunded orders under the same account or the same email address (ignoring case) disqualify; test and cancelled orders do not. Guests are recognised by email. An order with neither an account nor an email does not qualify.

Example: false
show_in_cart boolean

Allow the storefront to show this coupon before checkout. Coupon discounts only; sending true for an automatic discount returns DISCOUNT_TARGETS_FORBIDDEN.

Example: false
bxgy_buy_quantity integer

The quantity a shopper must add from the Buy X set.

Example: 2
bxgy_get_quantity integer

The quantity rewarded from the Get Y set.

Example: 1
bxgy_get_type string

Make reward items free, reduce their remaining value by a percentage, or deduct a fixed amount from each reward item. The cheapest qualifying items are the rewards, whatever their order in the cart.

Example: free
bxgy_get_value number

The percentage off each reward item, or the fixed amount deducted from each reward item in the store base currency, converted to the order currency at the market's exchange rate. Fixed means an amount off, not a final selling price. The deduction is capped at the remaining reward-item value. Omit this field when rewards are free. Fixed amounts use the base currency precision and the live money_amount_max.

Example: 50
bxgy_max_uses integer

The maximum number of complete Buy X Get Y sets that may apply to one order: a whole number from bxgy_max_uses_min through bxgy_max_uses_max in the limits response. Omit it or send null for no per-order cap; unlimited_sentinel (-1) is not accepted here.

Example: 1
bxgy_buy_items array<object>

Simple products, exact variants, collections, or categories that can satisfy Buy X. Each item contains item_type (product, variant, collection, category) and string item_id. An item qualifies when it matches any target in the list. Bought and reward items are always different units, even when the two lists overlap.

Example: [{"item_type": "product", "item_id": "12"}]
bxgy_get_items array<object>

Simple products, exact variants, collections, or categories that can be rewarded as Get Y, independently of Buy X targets. The shopper adds reward items to the cart; the discount never adds them. Whole variable products cannot be saved as product targets; select their exact variants.

Example: [{"item_type": "product", "item_id": "34"}]
bundle_value_mode string

Use fixed_price for a set price or percentage for a percentage reduction on each complete bundle.

Example: fixed_price
bundle_prices object

The price of one complete bundle, keyed by currency code. Include the base currency for fixed-price bundles; other market currencies without an entry use the converted base price.

Example: {"USD": "75.00"}
bundle_percentage number

The percentage reduction for each complete bundle when the value mode is percentage.

Example: 15
bundle_max_sets integer

The maximum number of complete bundle sets discounted on one order. Send -1 or null for no limit; an unlimited bundle is returned as null.

Example: 2
bundle_items array<object>

The products or variants and quantities required for one complete bundle. Provide between bundle_components_min and bundle_components_max different components. A product component matches any variant of that product; a variant component matches only that variant.

Example: [{"item_type": "product", "item_id": "12", "quantity": 1}, {"item_type": "variant", "item_id": "45", "quantity": 2}]

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

  • 400 DISCOUNT_NAME_REQUIRED

    Name is empty after trimming.

  • 400 DISCOUNT_NAME_TOO_LONG

    Name is longer than name_max_length.

  • 400 DISCOUNT_TYPE_INVALID

    Type is not a supported discount type.

  • 400 DISCOUNT_ACTIVATION_INVALID

    Activation is not coupon or automatic.

  • 400 DISCOUNT_CODE_REQUIRED

    A coupon discount has no code.

  • 400 DISCOUNT_CODE_AUTOMATIC_FORBIDDEN

    An automatic discount was sent a code.

  • 400 DISCOUNT_CODE_TOO_LONG

    The code is longer than code_max_length.

  • 400 DISCOUNT_CODE_CHARACTERS

    The code uses a character other than A–Z, digits, hyphen or underscore.

  • 400 DISCOUNT_PRIORITY_RANGE

    Priority is outside priority_min to max_priority.

  • 400 DISCOUNT_VALUE_RANGE

    A percentage value is not above 0 and at most 100.

  • 400 DISCOUNT_PERCENTAGE_TOO_PRECISE

    A percentage has more than percentage_decimal_places decimal places.

  • 400 DISCOUNT_VALUE_FORBIDDEN

    Value was sent for a type that does not take one.

  • 400 DISCOUNT_AMOUNTS_REQUIRED

    A fixed-amount discount has no amounts.

  • 400 DISCOUNT_AMOUNTS_FORBIDDEN

    Amounts were sent for a type that does not take them.

  • 400 DISCOUNT_CURRENCY_BASE_REQUIRED

    A money map is missing the store's base currency.

  • 400 DISCOUNT_CURRENCY_INVALID

    A money map uses a currency not assigned to the market.

  • 400 DISCOUNT_CURRENCY_VALUE_RANGE

    A money value is not greater than 0.

  • 400 DISCOUNT_CURRENCY_VALUE_TOO_LARGE

    A money value is above money_amount_max.

  • 400 DISCOUNT_CURRENCY_VALUE_TOO_PRECISE

    A money value, fixed Buy X Get Y value, tier threshold or fixed tier value has more decimal places than its currency.

  • 400 DISCOUNT_APPLIES_TO_INVALID

    Applies_to is not a supported value.

  • 400 DISCOUNT_ENTIRE_ORDER_ONLY

    A Buy X Get Y, bundle or tiered discount was not set to entire_order.

  • 400 DISCOUNT_ELIGIBILITY_INVALID

    Customer_eligibility is not a supported value.

  • 400 DISCOUNT_TARGETS_REQUIRED

    Specific targeting or eligibility was chosen without its id list, or a referenced id is malformed, does not exist, or belongs to another store.

  • 400 DISCOUNT_TARGETS_FORBIDDEN

    An id list was sent that does not match the targeting or eligibility, exclude_sale_items or show_in_cart was set where it is not supported, or a Buy X Get Y item has an unsupported item_type.

  • 400 DISCOUNT_MIN_QUANTITY_FORBIDDEN

    Min_quantity was sent for Buy X Get Y, bundle or tiered.

  • 400 DISCOUNT_MIN_QUANTITY_RANGE

    Min_quantity is below quantity_min.

  • 400 DISCOUNT_MIN_QUANTITY_TOO_LARGE

    Min_quantity is above min_quantity_max.

  • 400 DISCOUNT_MAX_DISCOUNT_FORBIDDEN

    Max_discount was sent for fixed-amount, Buy X Get Y or free gift.

  • 400 DISCOUNT_USAGE_LIMIT_RANGE

    Usage_limit is not -1, null, or within quantity_min to max_usage_limit.

  • 400 DISCOUNT_PER_CUSTOMER_RANGE

    Per_customer_limit is not -1, null, or within quantity_min to max_per_customer_limit.

  • 400 DISCOUNT_DATE_INVALID

    Starts_at or ends_at is not in YYYY-MM-DDTHH:mm:ss form.

  • 400 MARKET_DISCOUNT_DATE_INVALID

    Ends_at is not after starts_at.

  • 400 DISCOUNT_BXGY_FIELDS_FORBIDDEN

    Buy X Get Y fields were sent for another type.

  • 400 DISCOUNT_BXGY_BUY_REQUIRED

    Buy X Get Y has no valid buy items.

  • 400 DISCOUNT_BXGY_GET_REQUIRED

    Buy X Get Y has no valid reward items.

  • 400 DISCOUNT_BXGY_QUANTITY_RANGE

    A buy or reward quantity is outside 1 to max_bxgy_quantity.

  • 400 DISCOUNT_GET_TYPE_REQUIRED

    Buy X Get Y has no bxgy_get_type.

  • 400 DISCOUNT_GET_TYPE_INVALID

    Bxgy_get_type is not free, percentage or fixed.

  • 400 DISCOUNT_GET_VALUE_FORBIDDEN

    Bxgy_get_value was sent for free rewards.

  • 400 DISCOUNT_GET_VALUE_RANGE

    A percentage reward is not above 0 and at most 100.

  • 400 DISCOUNT_GET_VALUE_POSITIVE

    A fixed reward amount is not greater than 0.

  • 400 DISCOUNT_GET_VALUE_TOO_LARGE

    A fixed reward amount is above money_amount_max.

  • 400 DISCOUNT_MAX_USES_PER_ORDER_RANGE

    Bxgy_max_uses is below bxgy_max_uses_min.

  • 400 DISCOUNT_MAX_USES_PER_ORDER_TOO_LARGE

    Bxgy_max_uses is above bxgy_max_uses_max.

  • 400 DISCOUNT_BUNDLE_FIELDS_FORBIDDEN

    Bundle fields were sent for another type.

  • 400 DISCOUNT_BUNDLE_MODE_REQUIRED

    A bundle has no bundle_value_mode.

  • 400 DISCOUNT_BUNDLE_MODE_INVALID

    Bundle_value_mode is not fixed_price or percentage, the other mode's field was also sent (bundle_percentage with fixed_price, or bundle_prices with percentage), or a component's item_type is not product or variant.

  • 400 DISCOUNT_BUNDLE_PRICE_REQUIRED

    A fixed-price bundle has no bundle_prices.

  • 400 DISCOUNT_BUNDLE_PERCENT_REQUIRED

    A percentage bundle has no valid bundle_percentage.

  • 400 DISCOUNT_BUNDLE_ITEMS_RANGE

    The number of components is outside bundle_components_min to bundle_components_max, or a component has a blank item_id.

  • 400 DISCOUNT_BUNDLE_ITEM_DUPLICATE

    The same product or variant appears twice in the bundle.

  • 400 DISCOUNT_BUNDLE_ITEM_QUANTITY

    A component quantity is outside 1 to bundle_item_quantity_max.

  • 400 DISCOUNT_BUNDLE_MAX_SETS_RANGE

    Bundle_max_sets is not -1, null, or within bundle_max_sets_min to bundle_max_sets_max.

  • 400 DISCOUNT_GIFT_FIELDS_FORBIDDEN

    Gift fields were sent for another type.

  • 400 DISCOUNT_GIFT_MODE_INVALID

    Gift_mode is not offer or auto_add.

  • 400 DISCOUNT_GIFT_ITEMS_RANGE

    The number of gift items is outside gift_items_min to gift_items_max.

  • 400 DISCOUNT_GIFT_ITEM_DUPLICATE

    The same gift product or variant appears twice.

  • 400 DISCOUNT_GIFT_ITEM_QUANTITY

    A gift quantity is outside 1 to gift_item_quantity_max.

  • 400 DISCOUNT_GIFT_NOT_GIFT_ONLY

    A gift product_id is not positive, does not exist in the store, or is not marked gift-only.

  • 400 DISCOUNT_GIFT_VARIANT_REQUIRED

    A variable gift product has no variant_id.

  • 400 DISCOUNT_GIFT_VARIANT_INVALID

    The gift variant does not exist, belongs to another product, or was sent for a simple product.

  • 400 DISCOUNT_TIERS_COUNT

    The number of tiers is outside tiers_min to tiers_max.

  • 400 DISCOUNT_TIER_THRESHOLD_INVALID

    A tier threshold is negative or above money_amount_max. A threshold with more decimal places than the base currency returns DISCOUNT_CURRENCY_VALUE_TOO_PRECISE instead.

  • 400 DISCOUNT_TIER_THRESHOLD_ORDER

    Tier thresholds do not strictly increase.

  • 400 DISCOUNT_TIER_VALUE_INVALID

    A tier value is not positive, a percentage is above 100, or an amount is out of range.

  • 400 MARKET_DISCOUNT_RELATION_LIMIT_REACHED

    An id list is longer than its max_*_per_discount limit.

  • 400 MARKET_DISCOUNT_RELATION_DUPLICATE

    An id appears twice in a targeting, eligibility or Buy X Get Y list, or a product is targeted together with one of its own variants.

  • 400 STORE_API_INVALID_REQUEST_BODY

    The body is not valid JSON, or is not a JSON object.

  • 400 INVALID_INPUT

    A field has the wrong JSON type, for example a string where a number is expected.

  • 404 MARKET_NOT_FOUND

    Market does not exist in this store.

  • 409 MARKET_DISCOUNT_CODE_DUPLICATE

    Another discount in the market has this code, ignoring case.

  • 409 MARKET_DISCOUNT_PRIORITY_DUPLICATE

    Another discount in the market has this priority.

  • 404 MARKET_DISCOUNT_NOT_FOUND

    Discount does not exist in this market.

Bulk update discounts

POST write_markets

Delete, enable or disable selected discounts.

Read discounts/limits first. The batch must contain between 1 and list_max_limit unique, nonzero UUIDs: this is exactly the maximum pagination size, not max_per_market. Empty, duplicate, malformed or oversized selections and unsupported actions are rejected before any writes. Each discount is then processed independently within the authenticated store and requested market. HTTP 200 may contain failed items; inspect every results entry and retry only failed ids. Successful changes are retained if another item fails. Enable resumes the schedule; it does not force a scheduled or expired discount to become active. Each changed discount records the discount and market names in the audit log and publishes discounts/update or discounts/delete together with the change. Unchanged status emits neither. Existing order snapshots remain unchanged.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Body parameters

Name Type Description
ids required array<uuid>

Unique discount UUIDs, at most list_max_limit from the limits endpoint.

Example: ["12345678-1234-4234-8234-123456789012"]
action required string

delete, enable or disable.

Example: disable

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

  • 400 INVALID_INPUT

    Invalid action or ids: selection must be unique, valid UUIDs and contain 1 to list_max_limit items.

  • 400 STORE_API_INVALID_REQUEST_BODY

    Missing ids or malformed request body.

Delete a discount

DELETE write_markets

Remove a discount from a market.

Deleting a discount prevents it from applying to future orders and removes its saved targeting and eligibility configuration. Existing orders keep the discount amounts that were recorded when they were placed. A successful deletion publishes discounts/delete with the deleted discount's identity.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789
discountId required string

Discount id.

Example: 7c4b1e2f-9a8d-4c3b-b2a1-0f9e8d7c6b5a

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

  • 404 MARKET_NOT_FOUND

    Market does not exist in this store.

  • 404 MARKET_DISCOUNT_NOT_FOUND

    Discount does not exist in this market.

Enable a discount

POST write_markets

Allow a disabled discount to follow its schedule again.

After enabling, the returned status is active, scheduled, or expired according to the saved dates. Enabling a discount that is already enabled changes nothing. The response is the discount with its current usage_count, usage_held_count and usage_summary. A successful state change publishes discounts/update.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789
discountId required string

Discount id.

Example: 7c4b1e2f-9a8d-4c3b-b2a1-0f9e8d7c6b5a

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

  • 404 MARKET_NOT_FOUND

    Market does not exist in this store.

  • 404 MARKET_DISCOUNT_NOT_FOUND

    Discount does not exist in this market.

Disable a discount

POST write_markets

Pause a discount without deleting its configuration.

A disabled discount does not apply to new orders and remains disabled until it is enabled explicitly. Disabling a discount that is already disabled changes nothing. The response is the discount with its current usage_count, usage_held_count and usage_summary. A successful state change publishes discounts/update.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789
discountId required string

Discount id.

Example: 7c4b1e2f-9a8d-4c3b-b2a1-0f9e8d7c6b5a

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

  • 404 MARKET_NOT_FOUND

    Market does not exist in this store.

  • 404 MARKET_DISCOUNT_NOT_FOUND

    Discount does not exist in this market.

Get discount settings

GET read_markets

Read how discounts are allowed to combine in this market.

In single mode, one discount applies: every eligible automatic discount and every entered code are ranked together by priority_mode, and the first one wins. In stack mode, every eligible automatic discount applies, plus entered codes in ranked order up to coupon_limit; with auto_coupon_combine false, codes apply only when no automatic discount does. best_for_customer ranks by each discount's own saving; manual ranks by priority number, lowest first. Buy X Get Y, bundle and claimed gift offers use specific cart units, and two of them cannot use the same units: the higher-ranked keeps them and the other does not apply at all. Offers apply in three steps (Buy X Get Y, bundle and gift; then product, collection and category discounts; then order-wide discounts), and each uses the amount left after the earlier ones. With apply_to_quantity_priced false, quantity-priced items get no discount and do not count toward minimum spend, minimum quantity or tiers. Settings take effect the next time a cart or checkout is priced; placed orders keep their discounts.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

  • 404 MARKET_NOT_FOUND

    Market does not exist in this store.

Update discount settings

PUT write_markets

Change how discounts combine in this market.

Send only the settings you want to change; omitted or null settings keep their current values. stacking_mode accepts single or stack, and priority_mode accepts best_for_customer or manual. coupon_limit must be a whole number from 1 to the platform maximum, currently 5, and is checked in either mode; a value outside that range is rejected with MARKET_COUPON_LIMIT_OUT_OF_RANGE, and the error states the maximum. A new market starts with single, best_for_customer, 1, true and false. An unchanged request publishes no event; a successful change publishes discount_settings/update with all five settings.

Path parameters

Name Type Description
marketId required uuid

Market id.

Example: 9a1f2c3d-4e5f-6789-abcd-ef0123456789

Headers

Name Type Description
Authorization required string

Bearer Store API token.

Body parameters

Name Type Description
stacking_mode string

Use single to apply one discount per order, chosen by priority_mode, or stack to let every eligible automatic discount and up to coupon_limit codes apply together.

Example: single
priority_mode string

How discounts are ranked: best_for_customer by each discount's own saving, manual by priority number, lowest first. The ranking picks the single discount, fills the coupon limit, and decides which offer keeps items two offers both need. It ranks discounts one by one rather than searching for the largest combined saving.

Example: best_for_customer
coupon_limit integer

The maximum number of codes that may apply to one order in stack mode, from 1 to the platform maximum (currently 5). Automatic discounts do not count.

Example: 1
auto_coupon_combine boolean

In stack mode, true lets codes apply alongside automatic discounts; false lets codes apply only when no automatic discount applies. No effect in single mode.

Example: true
apply_to_quantity_priced boolean

When false, items with quantity pricing get no discount and do not count toward minimum spend, minimum quantity or tiers. When true, they are discounted like any other item, on top of their quantity price.

Example: false

Errors

  • 400 STORE_API_INVALID_REQUEST_BODY

    marketId must be a valid UUID.

  • 400 MARKET_STACKING_MODE_INVALID

    Stacking_mode is not single or stack.

  • 400 MARKET_PRIORITY_MODE_INVALID

    Priority_mode is not best_for_customer or manual.

  • 400 MARKET_COUPON_LIMIT_OUT_OF_RANGE

    Coupon_limit is below 1 or above the platform maximum (currently 5). The message states the maximum.

  • 400 STORE_API_INVALID_REQUEST_BODY

    The body is not valid JSON or a field has the wrong type.

  • 404 MARKET_NOT_FOUND

    Market does not exist in this store.