Packages

Update a package

Partially updates a Package. Every field is optional; only fields you send are written. Fields you omit retain their current values.

Requires the SETTINGS_MANAGE permission on the package's site. site_id and organisation_id are fixed at create time and cannot be changed here. Server-side, the same separate_couples_package_choices and permitted_membership_type_ids rules apply as on create.

When overnight_package_config.enabled flips, the package's hotel-room item choice is created (or removed) automatically — you don't need to send it explicitly.

put/shop/packages/{packageId}

Request body

namestring

Display name. Plain text only.

descriptionstring

Long-form description shown to customers. Markdown is rendered.

product_codestring nullable

External POS/PMS product code.

external_idstring nullable

External identifier used by integrations.

currencystring

The ISO-4217 currency code.

standard_priceinteger nullable

The standard price for this package, in the smallest currency unit (e.g. pence). Pass null to clear a previously-set standard price.

offered_onlineboolean

Whether the package is bookable via the public shopfront.

privateboolean

When true, only customers with the direct link can book this package.

visibility'public' | 'link_only' | 'private'

Visibility override controlling who can see this package on the shopfront. Same semantics as on create.

customers_onlyboolean

Restrict booking to registered customers.

members_onlyboolean

Restrict booking to permitted membership-type holders.

permitted_membership_type_idsstring[] nullable

Membership types whose members can book when members_only=true.

membership_booking_windows_enabledboolean

Whether to apply per-membership-type advance-booking windows.

item_choicesobject[]

Replacement set of item choices for this package. Same shape as PackageItemChoice on the Package schema.

category_idsstring[]

Category IDs for shopfront grouping.

customer_cancellation_permitted'allowed' | 'if_unpaid' | 'disallowed' nullable

Customer self-cancellation policy.

customer_cancellation_min_durationstring nullable

ISO 8601 duration before start at which cancellation is locked.

customer_reschedule_permitted'allowed' | 'disallowed' | 'unpaid' nullable

Whether and when customers can reschedule a booking of this type themselves. allowed = always. unpaid = only if no payment has been taken against the order. disallowed = never (admin only).

customer_reschedule_min_durationstring nullable

ISO 8601 duration before start at which rescheduling is locked.

max_daily_durationinteger nullable

Maximum minutes between first-item start and last-item end on each day.

max_advance_bookings_intervalstring nullable

ISO 8601 maximum advance-booking duration.

min_advance_bookings_intervalstring nullable

ISO 8601 minimum advance-booking duration.

min_guestsinteger nullable

Minimum guests per booking.

max_guestsinteger nullable

Maximum guests per booking. When either min_guests or max_guests is not exactly 2, separate_couples_package_choices is forced to false server-side.

prevent_choice_overlapsboolean nullable

Whether to prevent booking choices in this package from overlapping times.

separate_couples_package_choicesboolean nullable

For couples packages, whether each guest can independently pick choices. Forced to false for any other guest configuration.

image_idstring nullable

ID of an uploaded Media to use as the cover image. Pass null to clear.

default_revenue_centrestring nullable

Default revenue centre identifier to fall back to when balancing allocations. Must be a valid revenue centre at the package's site.

include_pricing_on_calendarboolean

Surface prices in calendar views.

max_per_basketinteger nullable

Max of this package per basket.

max_per_guestinteger nullable

Max of this package per guest per basket.

Example request

{
  "name": "Couples Spa Day",
  "description": "A full day of relaxation for two — includes a 60-minute\nmassage each, a two-course lunch, and full access to the\nthermal suite.\n",
  "product_code": "PKG-COUPLES-DAY",
  "external_id": "ext-couples-spa-day",
  "currency": "gbp",
  "standard_price": 5000,
  "availability_rules": [
    {
      "date_from": "2021-02-15",
      "date_to": "2021-02-15",
      "time_from": "11:00",
      "time_to": "17:00"
    }
  ],
  "permitted_membership_type_ids": [
    "00000000-0000-0000-0000-membership001"
  ],
  "membership_booking_windows": [
    {
      "max_advance_bookings_interval": "P2W",
      "min_advance_bookings_interval": "P2D"
    }
  ],
  "upsell_offerings": [
    {
      "offering_name": "Twilight massage",
      "offering_type": "appointment"
    }
  ],
  "cross_sell_offerings": [
    {
      "offering_name": "Twilight massage",
      "offering_type": "appointment"
    }
  ],
  "related_retail_offerings": [
    {
      "offering_name": "Twilight massage",
      "offering_type": "appointment"
    }
  ],
  "category_ids": [
    "5e932c0901d210625e3a8766"
  ],
  "customer_cancellation_min_duration": "PT24H",
  "customer_reschedule_permitted": "allowed",
  "customer_reschedule_min_duration": "PT24H",
  "max_daily_duration": 240,
  "max_advance_bookings_interval": "P2W",
  "min_advance_bookings_interval": "P2D",
  "min_guests": 2,
  "max_guests": 2,
  "image_id": "5f1234567890abcdef123456",
  "default_revenue_centre": "spa-treatments",
  "overnight_package_config": {
    "rate_id": "rate-king-bb",
    "num_nights": 1
  },
  "max_per_basket": 1,
  "max_per_guest": 1
}

Response

A single Package.

Example response

{
  "data": {
    "id": "5dcb47800000000000000010",
    "categories": [
      {
        "name": "Massages"
      }
    ],
    "cross_sell_offerings": [
      {
        "offering_name": "Twilight massage",
        "offering_type": "appointment"
      }
    ],
    "currency": "gbp",
    "customer_cancellation_min_duration": "P7D",
    "customer_cancellation_permitted": "allowed",
    "customer_reschedule_min_duration": "P7D",
    "customer_reschedule_permitted": "allowed",
    "description": "Buy together and save",
    "email_options": {
      "hide_prices": true
    },
    "image": {
      "file_name": "super-cool-photo.jpg",
      "mime_type": "image/jpeg",
      "original_url": "https://example.com/media/super-cool-photo.jpg",
      "size": 84256,
      "url": "https://example.com/media/super-cool-photo-thumbnail@2x.jpg"
    },
    "item_choices": [
      {
        "id": "5dcb47800000000000000025",
        "allow_overlaps": true,
        "auto_select_timeslot": true,
        "description": "Choose your type of massage.",
        "hide_times": true,
        "name": "Massage",
        "max_options": 2,
        "min_options": 1,
        "option_budget": 2000,
        "optional": true,
        "options": [
          {
            "id": "5dcb47800000000000000026",
            "item_type": "appointment",
            "offering": {
              "id": "5e932c0901d210625e3a8766",
              "categories": [
                {
                  "id": "5e932c0901d210625e3a8766",
                  "name": "Massage"
                }
              ],
              "currency": "gbp",
              "description": "Choose from classic, deep tissue and Swedish massage",
              "discounted_price_from": 4500,
              "duration": 30,
              "durations": [
                30
              ],
              "has_availability": true,
              "image": {
                "file_name": "super-cool-photo.jpg",
                "mime_type": "image/jpeg",
                "original_url": "https://example.com/media/super-cool-photo.jpg",
                "size": 84256,
                "url": "https://example.com/media/super-cool-photo-thumbnail@2x.jpg"
              },
              "max_guests": 2,
              "min_guests": 2,
              "name": "60 minute massage",
              "price_from": 5000,
              "price_to": 6500,
              "type": "appointment"
            },
            "price_change": 2000
          }
        ],
        "start_time_rules": [
          {
            "absolute_time_from": "12:00",
            "absolute_time_to": "12:30",
            "relative_mins_to": 30
          }
        ],
        "visible": true
      }
    ],
    "max_advance_bookings_interval": "P2W",
    "max_daily_duration": 240,
    "max_guests": 2,
    "max_per_basket": 1,
    "max_per_guest": 1,
    "members_only": true,
    "membership_booking_windows": [
      {
        "max_advance_bookings_interval": "P2W",
        "min_advance_bookings_interval": "P2D"
      }
    ],
    "membership_booking_windows_enabled": true,
    "min_advance_bookings_interval": "P2D",
    "min_guests": 2,
    "name": "Treatment and Yoga",
    "overnight_package_config": {
      "enabled": true,
      "rate_id": "5dcb47800000000000000010",
      "num_nights": 1
    },
    "prevent_choice_overlaps": true,
    "price_rules": [
      {
        "id": "5dcb47800000000000000010",
        "package_id": "5dcb47800000000000000010",
        "date_from": "2020-02-01",
        "date_to": "2020-04-01",
        "time_from": "10:00",
        "time_to": "14:00",
        "weekdays": [
          "monday"
        ],
        "price": 20000
      }
    ],
    "product_code": "MAS123",
    "related_retail_offerings": [
      {
        "offering_name": "Twilight massage",
        "offering_type": "appointment"
      }
    ],
    "site_id": "00000000-0000-0000-0000-111111111111",
    "standard_price": 5000,
    "upsell_offerings": [
      {
        "offering_name": "Twilight massage",
        "offering_type": "appointment"
      }
    ],
    "visibility": "public",
    "deleted_at": "2025-02-04T12:00:00+01:00",
    "updated_at": "2025-02-04T12:00:00+01:00"
  }
}

Changes

No recorded changes to this endpoint across all 1 revision of this API.