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

Sections, products & variants

A bundle is organized into sections — the groups a customer picks from. Sections come from GET /bundles/:id:

FieldTypeDescription
idnumberSection ID.
namestringSection title (e.g. “Choose a shirt”).
descriptionstringOptional description.
imageUrlstringOptional section image.
ordernumberDisplay order.
autoNextSectionbooleanThe merchant’s “advance to the next step once this one is satisfied” setting from the step editor. Mirror it — don’t hardcode either behaviour.
products[]arrayAllowed items in this section.

Each entry in products[] references a product (and optionally specific variants) allowed in that section:

FieldTypeDescription
bundleItemIdnumberThe bundle-item ID.
shopifyProductIdstringShopify product ID.
variantIdsstring[]Allowed variant IDs. Empty = all variants allowed.

Full product and variant detail comes from GET /bundles/:id/products (the SDK merges it into getBundle()):

Product

FieldTypeDescription
shopifyProductIdstringNumeric ID.
shopifyProductGidstringgid://shopify/Product/<id>.
titlestringProduct title.
handlestringURL handle.
imageUrlstringProduct image (may be empty).
statusstringACTIVE | ARCHIVED | DRAFT — see below.
tagsstring[]Product tags, minus Kitenzo’s internal bundle-builder-* control tags. Useful for grouping/filtering in your UI.
descriptionHtmlstringRaw Shopify product description HTML. Sanitise before rendering.
options[]arrayOption definitions (name, position, values[], swatches) in Shopify’s order.
variants[]arrayThe product’s variants.

Variant

FieldTypeDescription
shopifyVariantIdstringNumeric ID.
shopifyVariantGidstringgid://shopify/ProductVariant/<id>.
titlestringVariant title (e.g. “Small / Black”).
pricestringShop-currency price to 2 decimals, e.g. "29.99".
compareAtPricestring | nullThe variant’s own compare-at price. Meaningful for products sold alongside a bundle (an accessory upsell) — a bundle’s own saving comes from its discount.
skustringSKU (empty string if none).
availablebooleanWhether it can be purchased (see below).
inventoryQuantitynumberCurrent inventory quantity.
gramsnumberWeight in grams, as Shopify stores it — what the amount-of-weight limit rule measures.
optionValuesstring[]Option values positionally aligned with the product’s options (e.g. ["Small", "Black"]).
imagestring?Variant image — present only when the variant has its own; absent means “use the product image”.

options + optionValues exist so a custom UI can render one selector per option (Size / Colour) instead of a flat list of variant titles. Don’t split title on " / " — it doesn’t survive a real catalogue. The SDK ships the resolution logic: defaultOptionValues, reachableOptionValues, resolveVariant, selectOptionValue in @kitenzo/core.

An ARCHIVED or DRAFT product stays in the bundle until the merchant removes it, but it’s unpublished from the Online Store and cannot be added to the cart. Filter on status rather than rendering it as pickable.

available is computed as:

  1. true if inventory is not managed by Shopify for the variant; or
  2. true if the inventory policy is continue (oversell allowed); otherwise
  3. inventoryQuantity > 0.

Pass ?countryCode=DE (ISO 3166-1 alpha-2) to the products endpoint — or set countryCode on the SDK client/provider — and each variant sold in that market additionally carries:

FieldDescription
presentmentPricePrice in the shopper’s market currency (full precision — don’t assume 2 decimals).
presentmentCurrencyISO 4217 code, e.g. "EUR".
priceInShopCurrencyThe presentment price expressed back in shop currency.
availableForSaleWhether the variant is sellable in that market. false = not sold there — distinct from available (base-store stock). Gate selection on this when a market is set.

Set the same country as buyerIdentity.countryCode on your Shopify cart, or the displayed price won’t match checkout.