Promotions & Discounts
Quark Commerce has two separate discount mechanisms that can work together:
| System | How it works | User action needed |
|---|---|---|
| Promotions | Automatic, rule-based | None — evaluated on every basket fetch |
| Discount Codes | Code-based | User enters a code |
Automatic Promotions
Promotions are evaluated server-side every time a basket is fetched. If the basket meets the promotion conditions, discounts are automatically applied.
Promotion Types
| Type | Description | Example |
|---|---|---|
PercentageDiscount | % off items or cart | "20% off all tops" |
FixedAmountDiscount | Fixed $ off | "$10 off orders over $50" |
BuyXPayY | Buy X, pay for fewer | "Buy 3, pay for 2" |
BuyXGetY | Buy X, get Y free/discounted | "Buy 2 shirts, get 1 free" |
FreeShipping | Free shipping | "Free shipping over $75" |
DiscountedShipping | Reduced shipping cost | "Flat $2.99 shipping" |
FixedPriceBundle | Bundle for fixed price | "Any 3 t-shirts for $59.99" |
TieredDiscount | Discount increases with quantity | "5% off 2+, 10% off 5+, 15% off 10+" |
Basket Response with Promotions
{
"items": [...],
"subtotal": 89.97,
"appliedPromotions": [
{
"promotionId": "guid",
"name": "Summer Sale 20%",
"type": "PercentageDiscount",
"discountAmount": 18.00,
"badgeText": "SUMMER SALE",
"showOnProductPage": true,
"showOnCartPage": true
},
{
"promotionId": "guid",
"name": "Free Shipping Over $75",
"type": "FreeShipping",
"discountAmount": 0,
"hasFreeShipping": true
}
],
"totalPromotionDiscount": 18.00,
"hasFreeShipping": true,
"shippingDiscount": 5.99
}
Display Properties
Promotions include display hints for your UI:
| Field | Purpose |
|---|---|
badgeText | Badge label (e.g., "SALE", "NEW") to show on product cards |
bannerImageUrl | Optional banner image URL |
showOnProductPage | Whether to show on PDP |
showOnCartPage | Whether to show in cart |
Stacking Rules
- Stackable promotions can combine with other stackable promotions
- Non-stackable promotions are exclusive — only the highest-priority one applies
- Exclusion groups prevent specific promotions from combining (e.g., "Summer Sale" and "Flash Sale" can't both apply)
- Total discount is capped at the basket subtotal
Discount Codes
Discount codes are manually entered by the user. They work alongside automatic promotions.
Apply a Discount Code
POST /api/storefront/basket/{basketId}/discount-code
Content-Type: application/json
{
"code": "WELCOME10"
}
Success response — returns the updated basket with the discount applied.
Error responses:
{ "message": "Invalid discount code" }
{ "message": "Discount code has expired" }
{ "message": "Discount code usage limit reached" }
{ "message": "Minimum order amount not met" }
Remove a Discount Code
DELETE /api/storefront/basket/{basketId}/discount-code
Discount Code + Promotions
Both systems apply independently:
Subtotal: $89.97
Promotion discount: -$18.00 (Summer Sale 20%)
Discount code: -$10.00 (WELCOME10)
Shipping: $0.00 (Free shipping promotion)
─────────────────────────────
Total: $61.97
UI Recommendations
- Show
appliedPromotionswith theirbadgeTexton product cards and in the cart - Show the discount code input field in the cart/checkout
- Display the breakdown of all discounts clearly before the total