Skip to content
Kitenzo Headless is invite-only. To enable it on your store, email support@kitenzo.com.

Limit rules

Limit rules constrain what counts as a valid bundle (minimums, maximums, multiples, weight). They’re returned in limitRules[] on GET /bundles/:id.

{ "type": "total-number-of-products", "operation": "gte", "value": "3", "sectionId": null }
FieldTypeDescription
typestringThe rule type (below).
operationstringgt | gte | lt | lte | eq.
valuestringThe threshold.
sectionIdnumber | nullnull = applies to the whole bundle; otherwise scoped to a section.
typeConstrains
bundle-priceThe bundle price after discount.
bundle-price-before-discountThe bundle price before discount.
total-number-of-productsTotal count of all products. This is also how a step’s min/max picks are expressed (with the step’s sectionId).
amount-of-one-productThe quantity of any single product.
amount-of-one-variantThe quantity of any single variant (per-variant uniqueness, e.g. “at most 1 of each”).
number-of-different-productsCount of distinct products.
multiples-ofThe product count must be a multiple of value (e.g. 6, 12, 18).
amount-of-weightTotal weight of the selection, measured from each variant’s grams and compared in the shop’s weightUnit (on the bundle payload and /settings).

These mirror the engine’s server-side validator (/configure is the authority), so match them or your UI will under- or over-gate:

  • multiples-of ignores operation — 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-variant hold when every product/variant satisfies the rule, not just the most-picked one (identical for the common lte shape; different for gte/gt/eq).
  • Step pick counts: eq 8 = exactly 8; gte 3 + lte 5 = a range; only lte = optional with a ceiling; no rule = optional, unbounded. gt/lt are exclusive.
  • Weight: without variant grams, the rule can never fire client-side — the products endpoint serves grams for 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 (max can be UNBOUNDED).
  • 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 read errors for the human-readable reasons.
  • The SDK’s builder exposes violations as errors and overall validity through isSatisfied (preferred) / isComplete (legacy — see Hooks).
  • Only rules that target the bundle are returned to headless consumers (rules that gate free items are handled internally).