Skip to main content
Booking bundles (packages / codes) can be assigned to booking bundle groups, the same pattern as service groups and add-on groups. This is the contract for admin clients and native apps. For JSON:API conventions, see JSON-API Conventions.
JSON:API type: booking-bundle-groups. Bundles expose a nullable group relationship (booking-bundle-groups). Deleting a group detaches bundles (group_id is set to null); it does not delete the bundles.

Resource

Index is readable without a write permission. Create, update, and delete require create / update on any resource plus access to the organization (?o=).
Shop and native apps must load groups from the organization with include=offered_booking_bundle_groups or the related resource GET /api/v1/organizations/{slug}/offered-booking-bundle-groups.

Attributes

Write name (required, max 191) and optional description / order_index. Send translations as local_name_i18n.{locale} and description_i18n.{locale}.

Relationships

Allowed sort: order_index, name, created_at. Allowed filters: filter[ids], filter[search].

Bundle relationship and filters

Every booking-bundles resource has a nullable group relationship. Include it on list, read, and public catalog requests:

Filters on booking-bundles and available-booking-bundles

Send filter[without_group]=true as a string. A JSON boolean query value is rejected by the JSON:API decoder.
Assign or clear a group on create/update via the JSON:API relationship (same as services / add-ons):
Set relationships.group.data to null to ungroup.

Public catalog (shop and native customer apps)

Load the live groups that currently have at least one live bundle, then load bundles per group.
offered-booking-bundle-groups only returns groups that have at least one live bundle. Empty groups do not appear in the shop catalog.

How to render the package list

Match the web shop: one collapsible section per offered group (title = name, optional subtitle = description), then an Other section for filter[without_group]=true.
1

Load offered groups

Request offered_booking_bundle_groups (or the related resource). Sort by order_index.
2

Load bundles per group

For each group, request available-booking-bundles with filter[group_id] set to that group’s id, plus include=group,cover_image and sort=order_index.
3

Load ungrouped bundles

Request available-booking-bundles with filter[without_group]=true. If the collection is empty, hide the Other section.
4

Reuse service-group UI

This is the same layout as services (offered-service-groups + ungrouped services). Reuse that component; swap the resource type.
Do not invent grouping from bundle names. Always use relationships.group / filter[group_id]. After a group is deleted, previously grouped bundles show up under Other.

Admin (native admin app)

Mirror the web admin:
  1. Bundle form — taggable group select (create a group by typing a new name, same as service groups). Persist via the group relationship. Include group when loading a bundle.
  2. Bundle list — grouped panels by booking-bundle-groups (sort=order_index), plus an ungrouped section (filter[without_group]=true).
  3. CRUD — create/update/delete groups with name, description, and translations. On delete, keep the bundles; they become ungrouped.
Create payload:

Example group resource