Bundle
Private Bundle API endpoints
- GET/bundles
- POST/bundles
- GET/bundles/{bundle_id}
- PUT/bundles/{bundle_id}
- GET/bundles/{bundle_id}/items
- POST/bundles/{bundle_id}/items
- POST/bundles/{bundle_id}/items/batch
- GET/bundles/{bundle_id}/items/{item_id}
- PUT/bundles/{bundle_id}/items/{item_id}
- DELETE/bundles/{bundle_id}/items/{item_id}
- GET/bundles/{bundle_id}/groups
- POST/bundles/{bundle_id}/publish
- POST/bundles/{bundle_id}/unpublish
- POST/bundles/{bundle_id}/archive
- POST/bundles/{bundle_id}/metadata
- POST/bundles/{bundle_id}/plans
- GET/bundles/{bundle_id}/plans/{plan_id}
- PUT/bundles/{bundle_id}/plans/{plan_id}
- POST/bundles/{bundle_id}/plans/{plan_id}/archive
An API endpoint to get list of bundles. The private API can access both published and unpublished bundles.
Relation fields are only populated when requested through expand. Accepted values: images, rulesets, plans, preferences, filters, discounts, prices, items_count, tags, metadata. Unrequested relations come back as empty arrays (items_count as 0, metadata as null); tags and tags_meta are both driven by expand=tags. Unknown names are ignored.
Query parameters
pageoptionalintegerPage number for pagination
per_pageoptionalintegerItems per page
Defaults to 10.
ids[]optionalinteger[]Filter by bundle IDs. Values must be unique.
slugs[]optionalstring[]Filter by bundle slugs. Values must be unique.
tags[]optionalstring[]Filter by tags. Values must be unique.
publishedoptionalbooleanFilter by published status
configurableoptionalbooleanFilter by configurable bundles
digitaloptionalbooleanFilter by digital bundles
expand[]optionalstring[]List of relations to expand in the response.
sort[field]optionalstringField to sort by. Required whenever any sort[...] parameter is sent, so sort[direction] on its own is rejected.
Possible values: id, name.
sort[direction]optionalstringSort direction; defaults to asc.
Possible values: asc, desc.
Defaults to "asc".
Returnsobject
Bundles list response
This operation accepts no expand parameter, so the relation fields of the returned bundle are always empty. Read the bundle back with expand to see them.
Request body
configurableRequiredintegerPossible values: 0, 1.
selection_typeoptionalstring | nullRequired when configurable=1. When configurable=0 any value sent is ignored and stored as null.
Possible values: variant, product, single_product.
digitaloptionalintegerPossible values: 0, 1.
slugRequiredstringMust be unique among the shop's bundles.
nameoptionalstring | nullhidden_itemsoptionalintegerPossible values: 0, 1.
searchableoptionalintegerPossible values: 0, 1.
show_ruleset_nameoptionalintegerPossible values: 0, 1.
descriptionoptionalstring | nulldelivery_infooptionalstring | nullsetup_feeoptionalinteger | nullpre_order_end_atoptionalstring | nullDate in Y-m-d format. Must be today or later; past dates are rejected.
Format: date.
gifting_enabledoptionalintegerProhibited when digital=1.
Possible values: 0, 1.
pause_enabledoptionalinteger0 is only accepted on plans with the optional-pause feature; other shops must send 1.
Possible values: 0, 1.
price_typeoptionalstring | nullOnly accepted for configurable bundles; rejected when selection_type is single_product, when ruleset_type is total, or when discount_type is also non-null.
Possible values: total, per_item.
discount_typeoptionalstring | nullOnly accepted for configurable bundles; rejected when price_type is also non-null (except for single_product bundles).
Possible values: per_item, total, percentage.
ruleset_typeoptionalstringOmit the field to leave it unset; sending an explicit null is rejected. Only accepted for configurable bundles whose selection_type is not single_product.
Possible values: quantity, total.
appearance_typeoptionalstringOmit the field to leave it unset; sending an explicit null is rejected. Only accepted for configurable bundles whose selection_type is not single_product.
Possible values: one_step, two_step, without_ruleset.
quantity_selectorsoptionalinteger[] | nullOnly accepted for configurable bundles whose selection_type is variant or product; prohibited otherwise. Must be a JSON list, not an object.
collect_shipping_addressoptionalinteger | nullMust be 1 unless the bundle is digital; 0 is only accepted when digital=1.
Possible values: 0, 1.
funnel_idoptionalinteger | nulltagsoptionalobjectfiltersoptionalobjectOnly accepted for configurable bundles whose selection_type is variant or product; prohibited otherwise.
preferencesoptionalobjectOnly accepted for configurable bundles whose selection_type is variant or product; prohibited otherwise.
rulesetsoptionalobjectOnly accepted for configurable bundles whose selection_type is variant or product; prohibited otherwise.
imagesoptionalobjectReturnsBundle
Bundle created successfully
A detailed description of the bundle. The private API can access both published and unpublished bundles.
Relation fields are only populated when requested through expand. Accepted values: images, rulesets, plans, preferences, filters, discounts, prices, items_count, tags, metadata. Unrequested relations come back as empty arrays (items_count as 0, metadata as null); tags and tags_meta are both driven by expand=tags. Unknown names are ignored.
Path parameters
bundle_idRequiredintegerBundle ID
Query parameters
expand[]optionalstring[]List of relations to expand in the response.
ReturnsBundle
Bundle object response
This operation accepts no expand parameter, so the relation fields of the returned bundle are always empty. Read the bundle back with expand to see them.
Path parameters
bundle_idRequiredintegerBundle ID
Request body
slugoptionalstringMust be unique among the shop's bundles.
nameoptionalstringhidden_itemsoptionalintegerPossible values: 0, 1.
searchableoptionalintegerPossible values: 0, 1.
show_ruleset_nameoptionalintegerProhibited unless the bundle is configurable.
Possible values: 0, 1.
descriptionoptionalstring | nulldelivery_infooptionalstring | nullsetup_feeoptionalinteger | nullpre_order_end_atoptionalstring | nullDate in Y-m-d format. Must be today or later; past dates are rejected.
Format: date.
gifting_enabledoptionalintegerProhibited when the bundle is digital.
Possible values: 0, 1.
pause_enabledoptionalinteger0 is only accepted on plans with the optional-pause feature; other shops must send 1.
Possible values: 0, 1.
price_typeoptionalstring | nullMust be present in the payload whenever discount_type or ruleset_type is sent (send null if not applicable). Only accepted for configurable bundles; rejected when selection_type is single_product, when ruleset_type is total, or when discount_type is also non-null.
Possible values: total, per_item.
discount_typeoptionalstring | nullMust be present in the payload whenever price_type is sent (send null if not applicable). Only accepted for configurable bundles; rejected when price_type is also non-null (except for single_product bundles).
Possible values: per_item, total, percentage.
ruleset_typeoptionalstringOnly accepted for configurable bundles whose selection_type is not single_product. Rejected while the bundle has active subscriptions.
Possible values: quantity, total.
appearance_typeoptionalstringOnly accepted for configurable bundles whose selection_type is not single_product.
Possible values: one_step, two_step, without_ruleset.
quantity_selectorsoptionalinteger[] | nullOnly accepted when the bundle is configurable and its selection_type is not single_product. Must be a JSON list, not an object.
collect_shipping_addressoptionalintegerMust be 1 unless the bundle is digital; 0 is only accepted for digital bundles.
Possible values: 0, 1.
funnel_idoptionalinteger | nullchange_product_collection_idoptionalinteger | nullID of the product collection used for cross-product plan switching. Must be a non-archived collection of the shop whose type is 'subscription' or unset.
tagsoptionalobjectfiltersoptionalobjectOnly accepted when the bundle is configurable and its selection_type is not single_product.
preferencesoptionalobjectOnly accepted when the bundle is configurable and its selection_type is not single_product.
rulesetsoptionalobjectProhibited when the bundle is not configurable or its selection_type is single_product, and prohibited in the same request as ruleset_type; change the ruleset type in a separate call. After create, update and delete are applied the resulting set must hold at least one ruleset and must satisfy the range rules for the bundle's ruleset_type.
imagesoptionalobjectReturnsBundle
Bundle object response
An API endpoint to get list of items within a bundle.
Path parameters
bundle_idRequiredintegerBundle ID
Query parameters
pageoptionalintegerPage number for pagination
Defaults to 1.
per_pageoptionalintegerItems per page
Defaults to 10.
filters[]optionalobject[]Filter by metadata. A list of filter objects. Only preset metadata with single_line_string data type can be used for filtering.
variant_ids[]optionalinteger[]Filter by variant IDs
queryoptionalstringSearch query for bundle items
expand[]optionalstring[]List of relations to expand in the response.
Returnsobject
Bundle items list response
Path parameters
bundle_idRequiredintegerBundle ID
Request body
variant_idRequiredintegerProduct variant ID to add. Must be a non-archived one-time product variant belonging to the shop (not a gift card, not a bundle), and must not already be an item of this bundle.
quantityoptionalinteger | nullProhibited when the bundle is configurable; sending it returns 422 "Quantity is not available for configurable bundles."
positionoptionalinteger | nullextra_priceoptionalinteger | nullExtra price in cents. Only available for configurable bundles; sending it on a non-configurable bundle returns 422 "Extra price is only available for configurable bundles."
settingsoptionalobject | nullOnly available for configurable bundles whose selection type is not "single"; sending it otherwise returns 422.
ReturnsBundleItem
Bundle item created successfully
Path parameters
bundle_idRequiredintegerBundle ID
Request body
createRequiredobject[]Returnsobject
Batch bundle items created successfully
Get a specific bundle item by ID.
Path parameters
bundle_idRequiredintegerBundle ID
item_idRequiredintegerBundle item ID
Query parameters
expand[]optionalstring[]List of relations to expand in the response.
ReturnsBundleItem
Bundle item object response
Path parameters
bundle_idRequiredintegerBundle ID
item_idRequiredintegerBundle item ID
Request body
quantityoptionalinteger | nullProhibited when the bundle is configurable; sending it returns 422 "Quantity is not available for configurable bundles."
positionoptionalinteger | nullextra_priceoptionalinteger | nullExtra price in cents. Only available for configurable bundles; sending it on a non-configurable bundle returns 422 "Extra price is only available for configurable bundles."
settingsoptionalobjectOnly available for configurable bundles whose selection type is not "single"; sending it otherwise returns 422.
ReturnsBundleItem
Bundle item object response
Deleting is refused with 400 minimum_items_required when the bundle currently has fewer than 2 items. A bundle must keep at least 2 items.
Path parameters
bundle_idRequiredintegerBundle ID
item_idRequiredintegerBundle item ID
ReturnsBundleItem
Bundle item deleted
Error responses
400anyminimum_items_required. The bundle must keep at least 2 items.
An API endpoint to get list of groups within a bundle.
Path parameters
bundle_idRequiredintegerBundle ID
Query parameters
expand[]optionalstring[]List of relations to expand. items is always present and does not need to be requested. Available keys: product (the parent product of the group). Nested paths are supported, e.g. product.variants. Unknown keys are ignored.
pageoptionalintegerPage number for pagination
Defaults to 1.
per_pageoptionalintegerItems per page
Defaults to 10.
Returnsobject
Bundle groups list response
Error responses
400objectThe bundle is archived.
404objectBundle not found, or it belongs to another shop.
Path parameters
bundle_idRequiredintegerBundle ID
ReturnsBundle
Bundle object response
Error responses
400objectThe bundle is archived, is already published, has no items, or has no active (non-archived) plans.
Path parameters
bundle_idRequiredintegerBundle ID
ReturnsBundle
Bundle object response
Error responses
400objectThe bundle is archived, or is not currently published.
Path parameters
bundle_idRequiredintegerBundle ID
ReturnsBundle
Bundle object response
Error responses
400objectThe bundle is already archived, or still has active subscriptions.
Attaches and detaches metadata on the bundle. The bundle must not be archived, otherwise the request returns 400 (entity_archived).
Path parameters
bundle_idRequiredintegerBundle ID
Request body
Metadata sync request body
metadataRequiredobjectReturnsBundle
Bundle object response
Path parameters
bundle_idRequiredintegerBundle ID
Request body
typeRequiredstringA bundle may have at most one active one_time plan; creating a second one is rejected. There is no such limit on subscription plans.
Possible values: subscription, one_time.
nameRequiredstringpricesoptionalobject[]Required unless the bundle is configurable with no price_type; prohibited when the bundle is configurable and price_type is null. Must contain exactly one entry per active (non-archived) bundle ruleset. Quantities must be unique within a ruleset, the first entry's first range quantity must be 1, and every ruleset must repeat the same set of range quantities.
discountsoptionalobject[]Only accepted when the bundle is configurable, has no price_type, and has a discount_type; prohibited otherwise. Must contain exactly one entry per active (non-archived) bundle ruleset, with unique quantities per ruleset, a first range quantity of 1, and the same set of range quantities across every ruleset.
frequency_unitoptionalstringRequired for subscription type. day is rejected when a rebilling day is set without an anchor_date (soft-anchored billing).
Possible values: day, week, month.
frequency_countoptionalintegerRequired for subscription type. Minimum is 1, but rises to 2 when rebilling_day is set together with frequency_unit day.
shippingsoptionalobject[]Required for non-digital subscription bundles. Prohibited for digital bundles. Every entry must use the same shape: all buffered (add_unit/add_count) or all anchored (unit_day/unit_offset).
anchor_dateoptionalstring | nullDate in Y-m-d format; the literal 'today' is accepted and normalised. Only allowed when at least one shippings entry uses unit_day (anchored shipping), and required there when frequency_unit is day. Rejected when frequency_count is 1. For ad-hoc plans (no rebilling day set) it must be today. Otherwise it must fall between tomorrow and now plus frequency_count frequency_units.
Format: date.
rebilling_dayoptionalinteger | nullFor daily frequency on non-digital bundles. Must be 1. Mutually exclusive with rebilling_day_of_month and rebilling_day_of_week.
Possible values: 1.
rebilling_day_of_monthoptionalinteger | nullFor monthly frequency on non-digital bundles. Day of month (1-31). Mutually exclusive with rebilling_day and rebilling_day_of_week. When anchor_date is set it must equal that date's day of month.
rebilling_day_of_weekoptionalinteger | nullFor weekly frequency on non-digital bundles. Day of week (1-7, Monday = 1). Mutually exclusive with rebilling_day and rebilling_day_of_month. When anchor_date is set it must equal that date's ISO day of week.
cut_off_daysoptionalinteger | nullRequired when at least one shippings entry uses unit_day (anchored shipping), and prohibited otherwise. A non-zero value must not exceed the number of days in one billing cycle (frequency_unit x frequency_count).
cut_off_timeoptionalstring | nullTime in HH:MM (24h). Defaults to 23:59 when cut_off_days is sent without it. Rejected for digital bundles, for schedules that are not anchored (no unit_day), and when the shop's plan does not include the cut-off time feature.
charge_immediatelyoptionalintegerProhibited for digital bundles. Must be sent together with ship_immediately. For ad-hoc plans (no rebilling day set) only 1 is accepted.
Possible values: 0, 1.
ship_immediatelyoptionalintegerMust be sent together with charge_immediately. Cannot be 1 while charge_immediately is 0.
Possible values: 0, 1.
buffer_daysoptionalinteger | nullProhibited for digital bundles and rejected unless ship_immediately is 1. Maximum is frequency_count multiplied by 1 for day, 7 for week, or 31 for month frequency.
trial_priceoptionalinteger | nullProhibited on pre-order bundles and on plans with a rebilling day set (non ad-hoc). Must be sent together with trial_length_days.
trial_length_daysoptionalinteger | nullProhibited on pre-order bundles and on plans with a rebilling day set (non ad-hoc). Must be sent together with trial_price.
trial_single_orderoptionalintegerCan only be 1 on non-digital bundles and only when trial_length_days is set.
Possible values: 0, 1.
commitment_billing_countoptionalinteger | nullOnly accepted when the shop's plan includes commitment billing; otherwise rejected.
charges_limitoptionalinteger | nullsurvey_idoptionalinteger | nullReturnsBundlePlan
Bundle plan created successfully. Only variant, prices and discounts are populated; pricing and plan are always null on this response, so fetch the plan with GET and expand[]=plan to retrieve them.
Path parameters
bundle_idRequiredintegerBundle ID
plan_idRequiredintegerBundle plan ID
Query parameters
expand[]optionalstring[]List of relations to expand in the response.
ReturnsBundlePlan
Bundle plan object response
Path parameters
bundle_idRequiredintegerBundle ID
plan_idRequiredintegerBundle plan ID
Request body
nameoptionalstringpricesoptionalobject[]Cannot be changed while the plan has active subscriptions. Prohibited when the bundle is configurable with no price_type. When sent, must contain exactly one entry per active bundle ruleset, with a first range quantity of 1 and the same set of range quantities across every ruleset.
discountsoptionalobject[]Cannot be changed while the plan has active subscriptions. Only accepted when the bundle is configurable, has no price_type, and has a discount_type. Same per-ruleset range structure as prices.
shippingsoptionalobject[]Prohibited for digital bundles. Every entry must use the same shape: all buffered (add_unit/add_count) or all anchored (unit_day/unit_offset). Bounds are validated against the plan's existing frequency_unit and frequency_count, which this endpoint cannot change.
cut_off_daysoptionalinteger | nullRequired when the plan's shipping schedule is anchored (unit_day), prohibited otherwise. The anchored state comes from the shippings payload when sent, and from the stored schedule when it is not.
cut_off_timeoptionalstring | nullTime in HH:MM (24h). Defaults to 23:59 when cut_off_days is sent without it. Rejected for digital bundles, for non-anchored schedules, and when the shop's plan does not include the cut-off time feature.
charge_immediatelyoptionalintegerProhibited for digital bundles. Must be sent together with ship_immediately. Must be 1 when the stored plan has no rebilling day (ad-hoc billing).
Possible values: 0, 1.
ship_immediatelyoptionalintegerMust be sent together with charge_immediately and cannot be 1 while charge_immediately is 0. Cannot be set to 0 while buffer_days is still set, so clear buffer_days in the same request.
Possible values: 0, 1.
buffer_daysoptionalinteger | nullOnly accepted when the plan has exactly one shipment schedule entry, and only while ship_immediately is 1. Maximum is frequency_count multiplied by 1 for day, 7 for week, or 31 for month frequency.
trial_priceoptionalinteger | nullProhibited on pre-order bundles and on plans with a rebilling day set. trial_price and trial_length_days must be sent together.
trial_length_daysoptionalinteger | nullProhibited on pre-order bundles and on plans with a rebilling day set. trial_price and trial_length_days must be sent together.
trial_single_orderoptionalintegerCan only be 1 on non-digital bundles and only when the plan has a trial length.
Possible values: 0, 1.
commitment_billing_countoptionalinteger | nullOnly accepted when the shop's plan includes commitment billing.
charges_limitoptionalinteger | nullsurvey_idoptionalinteger | nullReturnsBundlePlan
Bundle plan object response. Only variant, prices and discounts are populated; pricing and plan are always null on this response, so fetch the plan with GET and expand[]=plan to retrieve them.
Archives a bundle plan. Rejected with 400 when the plan is already archived, when it is the bundle's last non-archived plan (error code last_active_plan), or when it still has active subscriptions (error code bundle_plan_has_active_subscriptions).
Path parameters
bundle_idRequiredintegerBundle ID
plan_idRequiredintegerBundle plan ID
ReturnsBundlePlan
Bundle plan object response. No relations are expanded on this response, so pricing, plan and variant are always null, and prices and discounts are always empty arrays.