Limit rules
Limit rules constrain what counts as a valid bundle (minimums, maximums, multiples, weight). They’re returned in limitRules[] on GET /bundles/:id.
Rule object
Section titled “Rule object”{ "type": "total-number-of-products", "operation": "gte", "value": "3", "sectionId": null }| Field | Type | Description |
|---|---|---|
type | string | The rule type (below). |
operation | string | gt | gte | lt | lte | eq. |
value | string | The threshold. |
sectionId | number | null | null = applies to the whole bundle; otherwise scoped to a section. |
Rule types
Section titled “Rule types”type | Constrains |
|---|---|
bundle-price | The bundle price after discount. |
bundle-price-before-discount | The bundle price before discount. |
total-number-of-products | Total count of all products. This is also how a step’s min/max picks are expressed (with the step’s sectionId). |
amount-of-one-product | The quantity of any single product. |
amount-of-one-variant | The quantity of any single variant (per-variant uniqueness, e.g. “at most 1 of each”). |
number-of-different-products | Count of distinct products. |
multiples-of | The product count must be a multiple of value (e.g. 6, 12, 18). |
amount-of-weight | Total weight of the selection, measured from each variant’s grams and compared in the shop’s weightUnit (on the bundle payload and /settings). |
Semantics worth knowing
Section titled “Semantics worth knowing”These mirror the engine’s server-side validator (/configure is the authority), so match them or your UI will under- or over-gate:
multiples-ofignoresoperation— the value is the unit and the count must be a positive multiple of it. A zero or blank unit is a no-op.amount-of-one-product/amount-of-one-varianthold when every product/variant satisfies the rule, not just the most-picked one (identical for the commonlteshape; different forgte/gt/eq).- Step pick counts:
eq 8= exactly 8;gte 3+lte 5= a range; onlylte= optional with a ceiling; no rule = optional, unbounded.gt/ltare exclusive. - Weight: without variant
grams, the rule can never fire client-side — the products endpoint servesgramsfor exactly this reason.
Reading them without re-deriving the maths
Section titled “Reading them without re-deriving the maths”The SDK turns rules into usable numbers and a single gate:
getSectionLimits(bundle, sectionId)→{ min, max }for one step (maxcan beUNBOUNDED).getBundleLimits(bundle)→ the bundle-wide “pick any N” window.builder.getState().isSatisfied→ whether the current selection would be accepted by/configure. Gate add-to-cart on this, and readerrorsfor the human-readable reasons.
How they’re validated
Section titled “How they’re validated”- The SDK’s builder exposes violations as
errorsand overall validity throughisSatisfied(preferred) /isComplete(legacy — see Hooks). - Only rules that target the bundle are returned to headless consumers (rules that gate free items are handled internally).