Promotions
GET /v1/catalog/promotions.
Required scope: catalog.promotions.read. Returns a plain array, not paginated.
What a promotion row tells you
Section titled “What a promotion row tells you”id, storeId, name, description, type (a closed set of values - see below),
startsAt/endsAt (nullable - a promotion without dates has no schedule restriction), isActive
(computed at request time: true only when the promotion is currently live, independent of your
filters), and two plain-language summary fields: eligibilitySummary (what a customer needs to buy
to qualify) and offerSummary (what they get) - e.g. "Buy any 2 qualifying items" /
"Fixed price £2.50".
Only customer-facing promotion types are returned
Section titled “Only customer-facing promotion types are returned”type is one of: MEAL_DEAL, MULTIBUY_SAME_PRODUCT, ANY_N_FIXED_PRICE,
MIX_MATCH_FIXED_PRICE, MULTIBUY_FIXED_PRICE, PRICE_CUT_FIXED_PRICE, PRICE_CUT_PERCENT,
PRICE_CUT_FIXED, TIMED_REDUCTION_PERCENT, TIMED_REDUCTION_FIXED, LOYALTY_PRICE.
Coupon promotions, staff discounts, and manually-applied discounts are never returned by this API, regardless of scope or filters - not redacted-down versions of them, entirely absent:
- Coupon codes are a marketing distribution mechanism, not public catalog data - if any client
holding
catalog.promotions.readcould list every active coupon and its code, that would defeat the point of controlling how a code reaches customers (email, print, in-store). - Staff and manual discounts are cashier-applied POS mechanics, gated by staff permissions at the till - they’re not a published offer a customer or an integration would ever act on.
Draft and archived promotions are also never returned, under any filter combination, and neither are internal “Quick % Off” presets used only inside the POS UI.
No raw builder configuration
Section titled “No raw builder configuration”The internal rule engine that evaluates promotions (product/category/group targeting, stacking
order, priority, apply mode) is implementation detail and is never exposed. eligibilitySummary
and offerSummary are the public-safe, human-readable description of what that engine decided -
not a serialization of its input.
Filters
Section titled “Filters”storeIdtype- exact match against the type list above.activeOnly(defaulttrue) - only currently-live promotions. Whenfalse, paused promotions are also included (draft/archived are still never included).activeAt(ISO 8601) - “what’s active at this specific instant” - forces the same live-only restriction asactiveOnly=trueregardless of theactiveOnlyvalue passed alongside it.
Related
Section titled “Related”- Products - promotions target products/categories internally, but that targeting detail isn’t exposed; a customer-facing integration typically just needs to know a promotion exists and what it offers, not exactly which SKUs trigger it.